Add base project
Implement auth method
82
.gitignore
vendored
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
# OSX
|
||||||
|
#
|
||||||
|
.DS_Store
|
||||||
|
|
||||||
|
# XDE
|
||||||
|
.expo/
|
||||||
|
|
||||||
|
# VSCode
|
||||||
|
.vscode/
|
||||||
|
jsconfig.json
|
||||||
|
|
||||||
|
# Xcode
|
||||||
|
#
|
||||||
|
build/
|
||||||
|
*.pbxuser
|
||||||
|
!default.pbxuser
|
||||||
|
*.mode1v3
|
||||||
|
!default.mode1v3
|
||||||
|
*.mode2v3
|
||||||
|
!default.mode2v3
|
||||||
|
*.perspectivev3
|
||||||
|
!default.perspectivev3
|
||||||
|
xcuserdata
|
||||||
|
*.xccheckout
|
||||||
|
*.moved-aside
|
||||||
|
DerivedData
|
||||||
|
*.hmap
|
||||||
|
*.ipa
|
||||||
|
*.xcuserstate
|
||||||
|
project.xcworkspace
|
||||||
|
|
||||||
|
# Android/IJ
|
||||||
|
#
|
||||||
|
.classpath
|
||||||
|
.cxx
|
||||||
|
.gradle
|
||||||
|
.idea
|
||||||
|
.project
|
||||||
|
.settings
|
||||||
|
local.properties
|
||||||
|
android.iml
|
||||||
|
|
||||||
|
# Cocoapods
|
||||||
|
#
|
||||||
|
example/ios/Pods
|
||||||
|
|
||||||
|
# Ruby
|
||||||
|
example/vendor/
|
||||||
|
|
||||||
|
# node.js
|
||||||
|
#
|
||||||
|
node_modules/
|
||||||
|
npm-debug.log
|
||||||
|
yarn-debug.log
|
||||||
|
yarn-error.log
|
||||||
|
|
||||||
|
# BUCK
|
||||||
|
buck-out/
|
||||||
|
\.buckd/
|
||||||
|
android/app/libs
|
||||||
|
android/keystores/debug.keystore
|
||||||
|
|
||||||
|
# Yarn
|
||||||
|
.yarn/*
|
||||||
|
!.yarn/patches
|
||||||
|
!.yarn/plugins
|
||||||
|
!.yarn/releases
|
||||||
|
!.yarn/sdks
|
||||||
|
!.yarn/versions
|
||||||
|
|
||||||
|
# Expo
|
||||||
|
.expo/
|
||||||
|
|
||||||
|
# Turborepo
|
||||||
|
.turbo/
|
||||||
|
|
||||||
|
# generated by bob
|
||||||
|
lib/
|
||||||
|
|
||||||
|
# React Native Codegen
|
||||||
|
ios/generated
|
||||||
|
android/generated
|
||||||
120
CONTRIBUTING.md
Normal file
@@ -0,0 +1,120 @@
|
|||||||
|
# Contributing
|
||||||
|
|
||||||
|
Contributions are always welcome, no matter how large or small!
|
||||||
|
|
||||||
|
## Development workflow
|
||||||
|
|
||||||
|
This project is a monorepo managed using [Yarn workspaces](https://yarnpkg.com/features/workspaces). It contains the following packages:
|
||||||
|
|
||||||
|
- The library package in the root directory.
|
||||||
|
- An example app in the `example/` directory.
|
||||||
|
|
||||||
|
To get started with the project, run `yarn` in the root directory to install the required dependencies for each package:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
yarn
|
||||||
|
```
|
||||||
|
|
||||||
|
> Since the project relies on Yarn workspaces, you cannot use [`npm`](https://github.com/npm/cli) for development.
|
||||||
|
|
||||||
|
The [example app](/example/) demonstrates usage of the library. You need to run it to test any changes you make.
|
||||||
|
|
||||||
|
It is configured to use the local version of the library, so any changes you make to the library's source code will be reflected in the example app. Changes to the library's JavaScript code will be reflected in the example app without a rebuild, but native code changes will require a rebuild of the example app.
|
||||||
|
|
||||||
|
If you want to use Android Studio or XCode to edit the native code, you can open the `example/android` or `example/ios` directories respectively in those editors. To edit the Objective-C or Swift files, open `example/ios/PubkyExample.xcworkspace` in XCode and find the source files at `Pods > Development Pods > react-native-pubky`.
|
||||||
|
|
||||||
|
To edit the Java or Kotlin files, open `example/android` in Android studio and find the source files at `react-native-pubky` under `Android`.
|
||||||
|
|
||||||
|
You can use various commands from the root directory to work with the project.
|
||||||
|
|
||||||
|
To start the packager:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
yarn example start
|
||||||
|
```
|
||||||
|
|
||||||
|
To run the example app on Android:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
yarn example android
|
||||||
|
```
|
||||||
|
|
||||||
|
To run the example app on iOS:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
yarn example ios
|
||||||
|
```
|
||||||
|
|
||||||
|
Make sure your code passes TypeScript and ESLint. Run the following to verify:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
yarn typecheck
|
||||||
|
yarn lint
|
||||||
|
```
|
||||||
|
|
||||||
|
To fix formatting errors, run the following:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
yarn lint --fix
|
||||||
|
```
|
||||||
|
|
||||||
|
Remember to add tests for your change if possible. Run the unit tests by:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
yarn test
|
||||||
|
```
|
||||||
|
|
||||||
|
### Commit message convention
|
||||||
|
|
||||||
|
We follow the [conventional commits specification](https://www.conventionalcommits.org/en) for our commit messages:
|
||||||
|
|
||||||
|
- `fix`: bug fixes, e.g. fix crash due to deprecated method.
|
||||||
|
- `feat`: new features, e.g. add new method to the module.
|
||||||
|
- `refactor`: code refactor, e.g. migrate from class components to hooks.
|
||||||
|
- `docs`: changes into documentation, e.g. add usage example for the module..
|
||||||
|
- `test`: adding or updating tests, e.g. add integration tests using detox.
|
||||||
|
- `chore`: tooling changes, e.g. change CI config.
|
||||||
|
|
||||||
|
Our pre-commit hooks verify that your commit message matches this format when committing.
|
||||||
|
|
||||||
|
### Linting and tests
|
||||||
|
|
||||||
|
[ESLint](https://eslint.org/), [Prettier](https://prettier.io/), [TypeScript](https://www.typescriptlang.org/)
|
||||||
|
|
||||||
|
We use [TypeScript](https://www.typescriptlang.org/) for type checking, [ESLint](https://eslint.org/) with [Prettier](https://prettier.io/) for linting and formatting the code, and [Jest](https://jestjs.io/) for testing.
|
||||||
|
|
||||||
|
Our pre-commit hooks verify that the linter and tests pass when committing.
|
||||||
|
|
||||||
|
### Publishing to npm
|
||||||
|
|
||||||
|
We use [release-it](https://github.com/release-it/release-it) to make it easier to publish new versions. It handles common tasks like bumping version based on semver, creating tags and releases etc.
|
||||||
|
|
||||||
|
To publish new versions, run the following:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
yarn release
|
||||||
|
```
|
||||||
|
|
||||||
|
### Scripts
|
||||||
|
|
||||||
|
The `package.json` file contains various scripts for common tasks:
|
||||||
|
|
||||||
|
- `yarn`: setup project by installing dependencies.
|
||||||
|
- `yarn typecheck`: type-check files with TypeScript.
|
||||||
|
- `yarn lint`: lint files with ESLint.
|
||||||
|
- `yarn test`: run unit tests with Jest.
|
||||||
|
- `yarn example start`: start the Metro server for the example app.
|
||||||
|
- `yarn example android`: run the example app on Android.
|
||||||
|
- `yarn example ios`: run the example app on iOS.
|
||||||
|
|
||||||
|
### Sending a pull request
|
||||||
|
|
||||||
|
> **Working on your first pull request?** You can learn how from this _free_ series: [How to Contribute to an Open Source Project on GitHub](https://app.egghead.io/playlists/how-to-contribute-to-an-open-source-project-on-github).
|
||||||
|
|
||||||
|
When you're sending a pull request:
|
||||||
|
|
||||||
|
- Prefer small pull requests focused on one change.
|
||||||
|
- Verify that linters and tests are passing.
|
||||||
|
- Review the documentation to make sure it looks good.
|
||||||
|
- Follow the pull request template when opening a pull request.
|
||||||
|
- For pull requests that change the API or implementation, discuss with maintainers first by opening an issue.
|
||||||
3
LICENSE
@@ -1,7 +1,6 @@
|
|||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2024 Pubky
|
Copyright (c) 2024 pubky
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
in the Software without restriction, including without limitation the rights
|
in the Software without restriction, including without limitation the rights
|
||||||
|
|||||||
44
README.md
@@ -1 +1,45 @@
|
|||||||
# react-native-pubky
|
# react-native-pubky
|
||||||
|
|
||||||
|
React Native implementation of [pubky](https://github.com/pubky/pubky)
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
```sh
|
||||||
|
npm install react-native-pubky
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { auth } from 'react-native-pubky';
|
||||||
|
|
||||||
|
const authRes = await auth("pubkyAuthUrl", "secretKey");
|
||||||
|
if (authRes.isErr()) {
|
||||||
|
console.log(authRes.error.message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.log(authRes.value);
|
||||||
|
```
|
||||||
|
|
||||||
|
## Update Bindings
|
||||||
|
|
||||||
|
After making changes to any of the Rust files, the bindings will need to be updated. To do this, run the following command:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
npm run update-bindings
|
||||||
|
```
|
||||||
|
|
||||||
|
Finally, ensure that `PubkyModule.kt`, `Pubky.swift`, `Pubky.mm` & `src/index.tsx` are updated accordingly based on the changes made to the Rust files.
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
MIT
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Resources
|
||||||
|
|
||||||
|
- Project created with: [create-react-native-library](https://github.com/callstack/react-native-builder-bob)
|
||||||
|
- [Building an Android App with Rust Using UniFFI](https://forgen.tech/en/blog/post/building-an-android-app-with-rust-using-uniffi)
|
||||||
|
- [Building an iOS App with Rust Using UniFFI](https://forgen.tech/en/blog/post/building-an-ios-app-with-rust-using-uniffi)
|
||||||
|
|
||||||
|
|||||||
101
android/build.gradle
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
buildscript {
|
||||||
|
// 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["Pubky_kotlinVersion"]
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
google()
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
classpath "com.android.tools.build:gradle:7.2.1"
|
||||||
|
// noinspection DifferentKotlinGradleVersion
|
||||||
|
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"
|
||||||
|
|
||||||
|
if (isNewArchitectureEnabled()) {
|
||||||
|
apply plugin: "com.facebook.react"
|
||||||
|
}
|
||||||
|
|
||||||
|
def getExtOrDefault(name) {
|
||||||
|
return rootProject.ext.has(name) ? rootProject.ext.get(name) : project.properties["Pubky_" + name]
|
||||||
|
}
|
||||||
|
|
||||||
|
def getExtOrIntegerDefault(name) {
|
||||||
|
return rootProject.ext.has(name) ? rootProject.ext.get(name) : (project.properties["Pubky_" + name]).toInteger()
|
||||||
|
}
|
||||||
|
|
||||||
|
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.pubky"
|
||||||
|
|
||||||
|
sourceSets {
|
||||||
|
main {
|
||||||
|
manifest.srcFile "src/main/AndroidManifestNew.xml"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
compileSdkVersion getExtOrIntegerDefault("compileSdkVersion")
|
||||||
|
|
||||||
|
defaultConfig {
|
||||||
|
minSdkVersion getExtOrIntegerDefault("minSdkVersion")
|
||||||
|
targetSdkVersion getExtOrIntegerDefault("targetSdkVersion")
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
buildTypes {
|
||||||
|
release {
|
||||||
|
minifyEnabled false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lintOptions {
|
||||||
|
disable "GradleCompatible"
|
||||||
|
}
|
||||||
|
|
||||||
|
compileOptions {
|
||||||
|
sourceCompatibility JavaVersion.VERSION_1_8
|
||||||
|
targetCompatibility JavaVersion.VERSION_1_8
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
mavenCentral()
|
||||||
|
google()
|
||||||
|
}
|
||||||
|
|
||||||
|
def kotlin_version = getExtOrDefault("kotlinVersion")
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
// 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"
|
||||||
|
implementation("net.java.dev.jna:jna:5.7.0@aar")
|
||||||
|
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4")
|
||||||
|
}
|
||||||
|
|
||||||
5
android/gradle.properties
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
Pubky_kotlinVersion=1.7.0
|
||||||
|
Pubky_minSdkVersion=21
|
||||||
|
Pubky_targetSdkVersion=31
|
||||||
|
Pubky_compileSdkVersion=31
|
||||||
|
Pubky_ndkversion=21.4.7075529
|
||||||
3
android/src/main/AndroidManifest.xml
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
package="com.pubky">
|
||||||
|
</manifest>
|
||||||
2
android/src/main/AndroidManifestNew.xml
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
</manifest>
|
||||||
43
android/src/main/java/com/pubky/PubkyModule.kt
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
package com.pubky
|
||||||
|
|
||||||
|
import com.facebook.react.bridge.Arguments
|
||||||
|
import com.facebook.react.bridge.ReactApplicationContext
|
||||||
|
import com.facebook.react.bridge.ReactContextBaseJavaModule
|
||||||
|
import com.facebook.react.bridge.ReactMethod
|
||||||
|
import com.facebook.react.bridge.Promise
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
import uniffi.mobile.auth
|
||||||
|
|
||||||
|
class PubkyModule(reactContext: ReactApplicationContext) :
|
||||||
|
ReactContextBaseJavaModule(reactContext) {
|
||||||
|
|
||||||
|
override fun getName(): String {
|
||||||
|
return NAME
|
||||||
|
}
|
||||||
|
|
||||||
|
@ReactMethod
|
||||||
|
fun auth(url: String, secretKey: String, promise: Promise) {
|
||||||
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
|
try {
|
||||||
|
val result = auth(url, secretKey)
|
||||||
|
val array = Arguments.createArray().apply {
|
||||||
|
result.forEach { pushString(it) }
|
||||||
|
}
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
promise.resolve(array)
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
promise.reject("Error", e.message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val NAME = "Pubky"
|
||||||
|
}
|
||||||
|
}
|
||||||
17
android/src/main/java/com/pubky/PubkyPackage.kt
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
package com.pubky
|
||||||
|
|
||||||
|
import com.facebook.react.ReactPackage
|
||||||
|
import com.facebook.react.bridge.NativeModule
|
||||||
|
import com.facebook.react.bridge.ReactApplicationContext
|
||||||
|
import com.facebook.react.uimanager.ViewManager
|
||||||
|
|
||||||
|
|
||||||
|
class PubkyPackage : ReactPackage {
|
||||||
|
override fun createNativeModules(reactContext: ReactApplicationContext): List<NativeModule> {
|
||||||
|
return listOf(PubkyModule(reactContext))
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> {
|
||||||
|
return emptyList()
|
||||||
|
}
|
||||||
|
}
|
||||||
11
android/src/main/java/com/pubky/pubky.iml
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<module type="JAVA_MODULE" version="4">
|
||||||
|
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||||
|
<exclude-output />
|
||||||
|
<content url="file://$MODULE_DIR$">
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$" isTestSource="false" packagePrefix="com.pubky" />
|
||||||
|
</content>
|
||||||
|
<orderEntry type="inheritedJdk" />
|
||||||
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
</component>
|
||||||
|
</module>
|
||||||
688
android/src/main/java/uniffi/mobile/mobile.kt
Normal file
@@ -0,0 +1,688 @@
|
|||||||
|
// This file was autogenerated by some hot garbage in the `uniffi` crate.
|
||||||
|
// Trust me, you don't want to mess with it!
|
||||||
|
|
||||||
|
@file:Suppress("NAME_SHADOWING")
|
||||||
|
|
||||||
|
package uniffi.mobile;
|
||||||
|
|
||||||
|
// Common helper code.
|
||||||
|
//
|
||||||
|
// Ideally this would live in a separate .kt file where it can be unittested etc
|
||||||
|
// in isolation, and perhaps even published as a re-useable package.
|
||||||
|
//
|
||||||
|
// However, it's important that the details of how this helper code works (e.g. the
|
||||||
|
// way that different builtin types are passed across the FFI) exactly match what's
|
||||||
|
// expected by the Rust code on the other side of the interface. In practice right
|
||||||
|
// now that means coming from the exact some version of `uniffi` that was used to
|
||||||
|
// compile the Rust component. The easiest way to ensure this is to bundle the Kotlin
|
||||||
|
// helpers directly inline like we're doing here.
|
||||||
|
|
||||||
|
import com.sun.jna.Library
|
||||||
|
import com.sun.jna.IntegerType
|
||||||
|
import com.sun.jna.Native
|
||||||
|
import com.sun.jna.Pointer
|
||||||
|
import com.sun.jna.Structure
|
||||||
|
import com.sun.jna.Callback
|
||||||
|
import com.sun.jna.ptr.*
|
||||||
|
import java.nio.ByteBuffer
|
||||||
|
import java.nio.ByteOrder
|
||||||
|
import java.nio.CharBuffer
|
||||||
|
import java.nio.charset.CodingErrorAction
|
||||||
|
import java.util.concurrent.ConcurrentHashMap
|
||||||
|
import kotlin.coroutines.resume
|
||||||
|
import kotlinx.coroutines.CancellableContinuation
|
||||||
|
import kotlinx.coroutines.suspendCancellableCoroutine
|
||||||
|
|
||||||
|
// This is a helper for safely working with byte buffers returned from the Rust code.
|
||||||
|
// A rust-owned buffer is represented by its capacity, its current length, and a
|
||||||
|
// pointer to the underlying data.
|
||||||
|
|
||||||
|
@Structure.FieldOrder("capacity", "len", "data")
|
||||||
|
open class RustBuffer : Structure() {
|
||||||
|
@JvmField var capacity: Int = 0
|
||||||
|
@JvmField var len: Int = 0
|
||||||
|
@JvmField var data: Pointer? = null
|
||||||
|
|
||||||
|
class ByValue: RustBuffer(), Structure.ByValue
|
||||||
|
class ByReference: RustBuffer(), Structure.ByReference
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
internal fun alloc(size: Int = 0) = rustCall() { status ->
|
||||||
|
_UniFFILib.INSTANCE.ffi_mobile_rustbuffer_alloc(size, status)
|
||||||
|
}.also {
|
||||||
|
if(it.data == null) {
|
||||||
|
throw RuntimeException("RustBuffer.alloc() returned null data pointer (size=${size})")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun create(capacity: Int, len: Int, data: Pointer?): RustBuffer.ByValue {
|
||||||
|
var buf = RustBuffer.ByValue()
|
||||||
|
buf.capacity = capacity
|
||||||
|
buf.len = len
|
||||||
|
buf.data = data
|
||||||
|
return buf
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun free(buf: RustBuffer.ByValue) = rustCall() { status ->
|
||||||
|
_UniFFILib.INSTANCE.ffi_mobile_rustbuffer_free(buf, status)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("TooGenericExceptionThrown")
|
||||||
|
fun asByteBuffer() =
|
||||||
|
this.data?.getByteBuffer(0, this.len.toLong())?.also {
|
||||||
|
it.order(ByteOrder.BIG_ENDIAN)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The equivalent of the `*mut RustBuffer` type.
|
||||||
|
* Required for callbacks taking in an out pointer.
|
||||||
|
*
|
||||||
|
* Size is the sum of all values in the struct.
|
||||||
|
*/
|
||||||
|
class RustBufferByReference : ByReference(16) {
|
||||||
|
/**
|
||||||
|
* Set the pointed-to `RustBuffer` to the given value.
|
||||||
|
*/
|
||||||
|
fun setValue(value: RustBuffer.ByValue) {
|
||||||
|
// NOTE: The offsets are as they are in the C-like struct.
|
||||||
|
val pointer = getPointer()
|
||||||
|
pointer.setInt(0, value.capacity)
|
||||||
|
pointer.setInt(4, value.len)
|
||||||
|
pointer.setPointer(8, value.data)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a `RustBuffer.ByValue` from this reference.
|
||||||
|
*/
|
||||||
|
fun getValue(): RustBuffer.ByValue {
|
||||||
|
val pointer = getPointer()
|
||||||
|
val value = RustBuffer.ByValue()
|
||||||
|
value.writeField("capacity", pointer.getInt(0))
|
||||||
|
value.writeField("len", pointer.getInt(4))
|
||||||
|
value.writeField("data", pointer.getPointer(8))
|
||||||
|
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is a helper for safely passing byte references into the rust code.
|
||||||
|
// It's not actually used at the moment, because there aren't many things that you
|
||||||
|
// can take a direct pointer to in the JVM, and if we're going to copy something
|
||||||
|
// then we might as well copy it into a `RustBuffer`. But it's here for API
|
||||||
|
// completeness.
|
||||||
|
|
||||||
|
@Structure.FieldOrder("len", "data")
|
||||||
|
open class ForeignBytes : Structure() {
|
||||||
|
@JvmField var len: Int = 0
|
||||||
|
@JvmField var data: Pointer? = null
|
||||||
|
|
||||||
|
class ByValue : ForeignBytes(), Structure.ByValue
|
||||||
|
}
|
||||||
|
// The FfiConverter interface handles converter types to and from the FFI
|
||||||
|
//
|
||||||
|
// All implementing objects should be public to support external types. When a
|
||||||
|
// type is external we need to import it's FfiConverter.
|
||||||
|
public interface FfiConverter<KotlinType, FfiType> {
|
||||||
|
// Convert an FFI type to a Kotlin type
|
||||||
|
fun lift(value: FfiType): KotlinType
|
||||||
|
|
||||||
|
// Convert an Kotlin type to an FFI type
|
||||||
|
fun lower(value: KotlinType): FfiType
|
||||||
|
|
||||||
|
// Read a Kotlin type from a `ByteBuffer`
|
||||||
|
fun read(buf: ByteBuffer): KotlinType
|
||||||
|
|
||||||
|
// Calculate bytes to allocate when creating a `RustBuffer`
|
||||||
|
//
|
||||||
|
// This must return at least as many bytes as the write() function will
|
||||||
|
// write. It can return more bytes than needed, for example when writing
|
||||||
|
// Strings we can't know the exact bytes needed until we the UTF-8
|
||||||
|
// encoding, so we pessimistically allocate the largest size possible (3
|
||||||
|
// bytes per codepoint). Allocating extra bytes is not really a big deal
|
||||||
|
// because the `RustBuffer` is short-lived.
|
||||||
|
fun allocationSize(value: KotlinType): Int
|
||||||
|
|
||||||
|
// Write a Kotlin type to a `ByteBuffer`
|
||||||
|
fun write(value: KotlinType, buf: ByteBuffer)
|
||||||
|
|
||||||
|
// Lower a value into a `RustBuffer`
|
||||||
|
//
|
||||||
|
// This method lowers a value into a `RustBuffer` rather than the normal
|
||||||
|
// FfiType. It's used by the callback interface code. Callback interface
|
||||||
|
// returns are always serialized into a `RustBuffer` regardless of their
|
||||||
|
// normal FFI type.
|
||||||
|
fun lowerIntoRustBuffer(value: KotlinType): RustBuffer.ByValue {
|
||||||
|
val rbuf = RustBuffer.alloc(allocationSize(value))
|
||||||
|
try {
|
||||||
|
val bbuf = rbuf.data!!.getByteBuffer(0, rbuf.capacity.toLong()).also {
|
||||||
|
it.order(ByteOrder.BIG_ENDIAN)
|
||||||
|
}
|
||||||
|
write(value, bbuf)
|
||||||
|
rbuf.writeField("len", bbuf.position())
|
||||||
|
return rbuf
|
||||||
|
} catch (e: Throwable) {
|
||||||
|
RustBuffer.free(rbuf)
|
||||||
|
throw e
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lift a value from a `RustBuffer`.
|
||||||
|
//
|
||||||
|
// This here mostly because of the symmetry with `lowerIntoRustBuffer()`.
|
||||||
|
// It's currently only used by the `FfiConverterRustBuffer` class below.
|
||||||
|
fun liftFromRustBuffer(rbuf: RustBuffer.ByValue): KotlinType {
|
||||||
|
val byteBuf = rbuf.asByteBuffer()!!
|
||||||
|
try {
|
||||||
|
val item = read(byteBuf)
|
||||||
|
if (byteBuf.hasRemaining()) {
|
||||||
|
throw RuntimeException("junk remaining in buffer after lifting, something is very wrong!!")
|
||||||
|
}
|
||||||
|
return item
|
||||||
|
} finally {
|
||||||
|
RustBuffer.free(rbuf)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FfiConverter that uses `RustBuffer` as the FfiType
|
||||||
|
public interface FfiConverterRustBuffer<KotlinType>: FfiConverter<KotlinType, RustBuffer.ByValue> {
|
||||||
|
override fun lift(value: RustBuffer.ByValue) = liftFromRustBuffer(value)
|
||||||
|
override fun lower(value: KotlinType) = lowerIntoRustBuffer(value)
|
||||||
|
}
|
||||||
|
// A handful of classes and functions to support the generated data structures.
|
||||||
|
// This would be a good candidate for isolating in its own ffi-support lib.
|
||||||
|
// Error runtime.
|
||||||
|
@Structure.FieldOrder("code", "error_buf")
|
||||||
|
internal open class RustCallStatus : Structure() {
|
||||||
|
@JvmField var code: Byte = 0
|
||||||
|
@JvmField var error_buf: RustBuffer.ByValue = RustBuffer.ByValue()
|
||||||
|
|
||||||
|
class ByValue: RustCallStatus(), Structure.ByValue
|
||||||
|
|
||||||
|
fun isSuccess(): Boolean {
|
||||||
|
return code == 0.toByte()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun isError(): Boolean {
|
||||||
|
return code == 1.toByte()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun isPanic(): Boolean {
|
||||||
|
return code == 2.toByte()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class InternalException(message: String) : Exception(message)
|
||||||
|
|
||||||
|
// Each top-level error class has a companion object that can lift the error from the call status's rust buffer
|
||||||
|
interface CallStatusErrorHandler<E> {
|
||||||
|
fun lift(error_buf: RustBuffer.ByValue): E;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helpers for calling Rust
|
||||||
|
// In practice we usually need to be synchronized to call this safely, so it doesn't
|
||||||
|
// synchronize itself
|
||||||
|
|
||||||
|
// Call a rust function that returns a Result<>. Pass in the Error class companion that corresponds to the Err
|
||||||
|
private inline fun <U, E: Exception> rustCallWithError(errorHandler: CallStatusErrorHandler<E>, callback: (RustCallStatus) -> U): U {
|
||||||
|
var status = RustCallStatus();
|
||||||
|
val return_value = callback(status)
|
||||||
|
checkCallStatus(errorHandler, status)
|
||||||
|
return return_value
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check RustCallStatus and throw an error if the call wasn't successful
|
||||||
|
private fun<E: Exception> checkCallStatus(errorHandler: CallStatusErrorHandler<E>, status: RustCallStatus) {
|
||||||
|
if (status.isSuccess()) {
|
||||||
|
return
|
||||||
|
} else if (status.isError()) {
|
||||||
|
throw errorHandler.lift(status.error_buf)
|
||||||
|
} else if (status.isPanic()) {
|
||||||
|
// when the rust code sees a panic, it tries to construct a rustbuffer
|
||||||
|
// with the message. but if that code panics, then it just sends back
|
||||||
|
// an empty buffer.
|
||||||
|
if (status.error_buf.len > 0) {
|
||||||
|
throw InternalException(FfiConverterString.lift(status.error_buf))
|
||||||
|
} else {
|
||||||
|
throw InternalException("Rust panic")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw InternalException("Unknown rust call status: $status.code")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CallStatusErrorHandler implementation for times when we don't expect a CALL_ERROR
|
||||||
|
object NullCallStatusErrorHandler: CallStatusErrorHandler<InternalException> {
|
||||||
|
override fun lift(error_buf: RustBuffer.ByValue): InternalException {
|
||||||
|
RustBuffer.free(error_buf)
|
||||||
|
return InternalException("Unexpected CALL_ERROR")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call a rust function that returns a plain value
|
||||||
|
private inline fun <U> rustCall(callback: (RustCallStatus) -> U): U {
|
||||||
|
return rustCallWithError(NullCallStatusErrorHandler, callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
// IntegerType that matches Rust's `usize` / C's `size_t`
|
||||||
|
public class USize(value: Long = 0) : IntegerType(Native.SIZE_T_SIZE, value, true) {
|
||||||
|
// This is needed to fill in the gaps of IntegerType's implementation of Number for Kotlin.
|
||||||
|
override fun toByte() = toInt().toByte()
|
||||||
|
// Needed until https://youtrack.jetbrains.com/issue/KT-47902 is fixed.
|
||||||
|
@Deprecated("`toInt().toChar()` is deprecated")
|
||||||
|
override fun toChar() = toInt().toChar()
|
||||||
|
override fun toShort() = toInt().toShort()
|
||||||
|
|
||||||
|
fun writeToBuffer(buf: ByteBuffer) {
|
||||||
|
// Make sure we always write usize integers using native byte-order, since they may be
|
||||||
|
// casted to pointer values
|
||||||
|
buf.order(ByteOrder.nativeOrder())
|
||||||
|
try {
|
||||||
|
when (Native.SIZE_T_SIZE) {
|
||||||
|
4 -> buf.putInt(toInt())
|
||||||
|
8 -> buf.putLong(toLong())
|
||||||
|
else -> throw RuntimeException("Invalid SIZE_T_SIZE: ${Native.SIZE_T_SIZE}")
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
buf.order(ByteOrder.BIG_ENDIAN)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
val size: Int
|
||||||
|
get() = Native.SIZE_T_SIZE
|
||||||
|
|
||||||
|
fun readFromBuffer(buf: ByteBuffer) : USize {
|
||||||
|
// Make sure we always read usize integers using native byte-order, since they may be
|
||||||
|
// casted from pointer values
|
||||||
|
buf.order(ByteOrder.nativeOrder())
|
||||||
|
try {
|
||||||
|
return when (Native.SIZE_T_SIZE) {
|
||||||
|
4 -> USize(buf.getInt().toLong())
|
||||||
|
8 -> USize(buf.getLong())
|
||||||
|
else -> throw RuntimeException("Invalid SIZE_T_SIZE: ${Native.SIZE_T_SIZE}")
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
buf.order(ByteOrder.BIG_ENDIAN)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Map handles to objects
|
||||||
|
//
|
||||||
|
// This is used when the Rust code expects an opaque pointer to represent some foreign object.
|
||||||
|
// Normally we would pass a pointer to the object, but JNA doesn't support getting a pointer from an
|
||||||
|
// object reference , nor does it support leaking a reference to Rust.
|
||||||
|
//
|
||||||
|
// Instead, this class maps USize values to objects so that we can pass a pointer-sized type to
|
||||||
|
// Rust when it needs an opaque pointer.
|
||||||
|
//
|
||||||
|
// TODO: refactor callbacks to use this class
|
||||||
|
internal class UniFfiHandleMap<T: Any> {
|
||||||
|
private val map = ConcurrentHashMap<USize, T>()
|
||||||
|
// Use AtomicInteger for our counter, since we may be on a 32-bit system. 4 billion possible
|
||||||
|
// values seems like enough. If somehow we generate 4 billion handles, then this will wrap
|
||||||
|
// around back to zero and we can assume the first handle generated will have been dropped by
|
||||||
|
// then.
|
||||||
|
private val counter = java.util.concurrent.atomic.AtomicInteger(0)
|
||||||
|
|
||||||
|
val size: Int
|
||||||
|
get() = map.size
|
||||||
|
|
||||||
|
fun insert(obj: T): USize {
|
||||||
|
val handle = USize(counter.getAndAdd(1).toLong())
|
||||||
|
map.put(handle, obj)
|
||||||
|
return handle
|
||||||
|
}
|
||||||
|
|
||||||
|
fun get(handle: USize): T? {
|
||||||
|
return map.get(handle)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun remove(handle: USize): T? {
|
||||||
|
return map.remove(handle)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FFI type for Rust future continuations
|
||||||
|
internal interface UniFffiRustFutureContinuationCallbackType : com.sun.jna.Callback {
|
||||||
|
fun callback(continuationHandle: USize, pollResult: Short);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Contains loading, initialization code,
|
||||||
|
// and the FFI Function declarations in a com.sun.jna.Library.
|
||||||
|
@Synchronized
|
||||||
|
private fun findLibraryName(componentName: String): String {
|
||||||
|
val libOverride = System.getProperty("uniffi.component.$componentName.libraryOverride")
|
||||||
|
if (libOverride != null) {
|
||||||
|
return libOverride
|
||||||
|
}
|
||||||
|
return "mobile"
|
||||||
|
}
|
||||||
|
|
||||||
|
private inline fun <reified Lib : Library> loadIndirect(
|
||||||
|
componentName: String
|
||||||
|
): Lib {
|
||||||
|
return Native.load<Lib>(findLibraryName(componentName), Lib::class.java)
|
||||||
|
}
|
||||||
|
|
||||||
|
// A JNA Library to expose the extern-C FFI definitions.
|
||||||
|
// This is an implementation detail which will be called internally by the public API.
|
||||||
|
|
||||||
|
internal interface _UniFFILib : Library {
|
||||||
|
companion object {
|
||||||
|
internal val INSTANCE: _UniFFILib by lazy {
|
||||||
|
loadIndirect<_UniFFILib>(componentName = "mobile")
|
||||||
|
.also { lib: _UniFFILib ->
|
||||||
|
uniffiCheckContractApiVersion(lib)
|
||||||
|
uniffiCheckApiChecksums(lib)
|
||||||
|
uniffiRustFutureContinuationCallback.register(lib)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun uniffi_mobile_fn_func_auth(`url`: RustBuffer.ByValue,`secretKey`: RustBuffer.ByValue,
|
||||||
|
): Pointer
|
||||||
|
fun uniffi_mobile_fn_func_myexample(_uniffi_out_err: RustCallStatus,
|
||||||
|
): RustBuffer.ByValue
|
||||||
|
fun ffi_mobile_rustbuffer_alloc(`size`: Int,_uniffi_out_err: RustCallStatus,
|
||||||
|
): RustBuffer.ByValue
|
||||||
|
fun ffi_mobile_rustbuffer_from_bytes(`bytes`: ForeignBytes.ByValue,_uniffi_out_err: RustCallStatus,
|
||||||
|
): RustBuffer.ByValue
|
||||||
|
fun ffi_mobile_rustbuffer_free(`buf`: RustBuffer.ByValue,_uniffi_out_err: RustCallStatus,
|
||||||
|
): Unit
|
||||||
|
fun ffi_mobile_rustbuffer_reserve(`buf`: RustBuffer.ByValue,`additional`: Int,_uniffi_out_err: RustCallStatus,
|
||||||
|
): RustBuffer.ByValue
|
||||||
|
fun ffi_mobile_rust_future_continuation_callback_set(`callback`: UniFffiRustFutureContinuationCallbackType,
|
||||||
|
): Unit
|
||||||
|
fun ffi_mobile_rust_future_poll_u8(`handle`: Pointer,`uniffiCallback`: USize,
|
||||||
|
): Unit
|
||||||
|
fun ffi_mobile_rust_future_cancel_u8(`handle`: Pointer,
|
||||||
|
): Unit
|
||||||
|
fun ffi_mobile_rust_future_free_u8(`handle`: Pointer,
|
||||||
|
): Unit
|
||||||
|
fun ffi_mobile_rust_future_complete_u8(`handle`: Pointer,_uniffi_out_err: RustCallStatus,
|
||||||
|
): Byte
|
||||||
|
fun ffi_mobile_rust_future_poll_i8(`handle`: Pointer,`uniffiCallback`: USize,
|
||||||
|
): Unit
|
||||||
|
fun ffi_mobile_rust_future_cancel_i8(`handle`: Pointer,
|
||||||
|
): Unit
|
||||||
|
fun ffi_mobile_rust_future_free_i8(`handle`: Pointer,
|
||||||
|
): Unit
|
||||||
|
fun ffi_mobile_rust_future_complete_i8(`handle`: Pointer,_uniffi_out_err: RustCallStatus,
|
||||||
|
): Byte
|
||||||
|
fun ffi_mobile_rust_future_poll_u16(`handle`: Pointer,`uniffiCallback`: USize,
|
||||||
|
): Unit
|
||||||
|
fun ffi_mobile_rust_future_cancel_u16(`handle`: Pointer,
|
||||||
|
): Unit
|
||||||
|
fun ffi_mobile_rust_future_free_u16(`handle`: Pointer,
|
||||||
|
): Unit
|
||||||
|
fun ffi_mobile_rust_future_complete_u16(`handle`: Pointer,_uniffi_out_err: RustCallStatus,
|
||||||
|
): Short
|
||||||
|
fun ffi_mobile_rust_future_poll_i16(`handle`: Pointer,`uniffiCallback`: USize,
|
||||||
|
): Unit
|
||||||
|
fun ffi_mobile_rust_future_cancel_i16(`handle`: Pointer,
|
||||||
|
): Unit
|
||||||
|
fun ffi_mobile_rust_future_free_i16(`handle`: Pointer,
|
||||||
|
): Unit
|
||||||
|
fun ffi_mobile_rust_future_complete_i16(`handle`: Pointer,_uniffi_out_err: RustCallStatus,
|
||||||
|
): Short
|
||||||
|
fun ffi_mobile_rust_future_poll_u32(`handle`: Pointer,`uniffiCallback`: USize,
|
||||||
|
): Unit
|
||||||
|
fun ffi_mobile_rust_future_cancel_u32(`handle`: Pointer,
|
||||||
|
): Unit
|
||||||
|
fun ffi_mobile_rust_future_free_u32(`handle`: Pointer,
|
||||||
|
): Unit
|
||||||
|
fun ffi_mobile_rust_future_complete_u32(`handle`: Pointer,_uniffi_out_err: RustCallStatus,
|
||||||
|
): Int
|
||||||
|
fun ffi_mobile_rust_future_poll_i32(`handle`: Pointer,`uniffiCallback`: USize,
|
||||||
|
): Unit
|
||||||
|
fun ffi_mobile_rust_future_cancel_i32(`handle`: Pointer,
|
||||||
|
): Unit
|
||||||
|
fun ffi_mobile_rust_future_free_i32(`handle`: Pointer,
|
||||||
|
): Unit
|
||||||
|
fun ffi_mobile_rust_future_complete_i32(`handle`: Pointer,_uniffi_out_err: RustCallStatus,
|
||||||
|
): Int
|
||||||
|
fun ffi_mobile_rust_future_poll_u64(`handle`: Pointer,`uniffiCallback`: USize,
|
||||||
|
): Unit
|
||||||
|
fun ffi_mobile_rust_future_cancel_u64(`handle`: Pointer,
|
||||||
|
): Unit
|
||||||
|
fun ffi_mobile_rust_future_free_u64(`handle`: Pointer,
|
||||||
|
): Unit
|
||||||
|
fun ffi_mobile_rust_future_complete_u64(`handle`: Pointer,_uniffi_out_err: RustCallStatus,
|
||||||
|
): Long
|
||||||
|
fun ffi_mobile_rust_future_poll_i64(`handle`: Pointer,`uniffiCallback`: USize,
|
||||||
|
): Unit
|
||||||
|
fun ffi_mobile_rust_future_cancel_i64(`handle`: Pointer,
|
||||||
|
): Unit
|
||||||
|
fun ffi_mobile_rust_future_free_i64(`handle`: Pointer,
|
||||||
|
): Unit
|
||||||
|
fun ffi_mobile_rust_future_complete_i64(`handle`: Pointer,_uniffi_out_err: RustCallStatus,
|
||||||
|
): Long
|
||||||
|
fun ffi_mobile_rust_future_poll_f32(`handle`: Pointer,`uniffiCallback`: USize,
|
||||||
|
): Unit
|
||||||
|
fun ffi_mobile_rust_future_cancel_f32(`handle`: Pointer,
|
||||||
|
): Unit
|
||||||
|
fun ffi_mobile_rust_future_free_f32(`handle`: Pointer,
|
||||||
|
): Unit
|
||||||
|
fun ffi_mobile_rust_future_complete_f32(`handle`: Pointer,_uniffi_out_err: RustCallStatus,
|
||||||
|
): Float
|
||||||
|
fun ffi_mobile_rust_future_poll_f64(`handle`: Pointer,`uniffiCallback`: USize,
|
||||||
|
): Unit
|
||||||
|
fun ffi_mobile_rust_future_cancel_f64(`handle`: Pointer,
|
||||||
|
): Unit
|
||||||
|
fun ffi_mobile_rust_future_free_f64(`handle`: Pointer,
|
||||||
|
): Unit
|
||||||
|
fun ffi_mobile_rust_future_complete_f64(`handle`: Pointer,_uniffi_out_err: RustCallStatus,
|
||||||
|
): Double
|
||||||
|
fun ffi_mobile_rust_future_poll_pointer(`handle`: Pointer,`uniffiCallback`: USize,
|
||||||
|
): Unit
|
||||||
|
fun ffi_mobile_rust_future_cancel_pointer(`handle`: Pointer,
|
||||||
|
): Unit
|
||||||
|
fun ffi_mobile_rust_future_free_pointer(`handle`: Pointer,
|
||||||
|
): Unit
|
||||||
|
fun ffi_mobile_rust_future_complete_pointer(`handle`: Pointer,_uniffi_out_err: RustCallStatus,
|
||||||
|
): Pointer
|
||||||
|
fun ffi_mobile_rust_future_poll_rust_buffer(`handle`: Pointer,`uniffiCallback`: USize,
|
||||||
|
): Unit
|
||||||
|
fun ffi_mobile_rust_future_cancel_rust_buffer(`handle`: Pointer,
|
||||||
|
): Unit
|
||||||
|
fun ffi_mobile_rust_future_free_rust_buffer(`handle`: Pointer,
|
||||||
|
): Unit
|
||||||
|
fun ffi_mobile_rust_future_complete_rust_buffer(`handle`: Pointer,_uniffi_out_err: RustCallStatus,
|
||||||
|
): RustBuffer.ByValue
|
||||||
|
fun ffi_mobile_rust_future_poll_void(`handle`: Pointer,`uniffiCallback`: USize,
|
||||||
|
): Unit
|
||||||
|
fun ffi_mobile_rust_future_cancel_void(`handle`: Pointer,
|
||||||
|
): Unit
|
||||||
|
fun ffi_mobile_rust_future_free_void(`handle`: Pointer,
|
||||||
|
): Unit
|
||||||
|
fun ffi_mobile_rust_future_complete_void(`handle`: Pointer,_uniffi_out_err: RustCallStatus,
|
||||||
|
): Unit
|
||||||
|
fun uniffi_mobile_checksum_func_auth(
|
||||||
|
): Short
|
||||||
|
fun uniffi_mobile_checksum_func_myexample(
|
||||||
|
): Short
|
||||||
|
fun ffi_mobile_uniffi_contract_version(
|
||||||
|
): Int
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun uniffiCheckContractApiVersion(lib: _UniFFILib) {
|
||||||
|
// Get the bindings contract version from our ComponentInterface
|
||||||
|
val bindings_contract_version = 24
|
||||||
|
// Get the scaffolding contract version by calling the into the dylib
|
||||||
|
val scaffolding_contract_version = lib.ffi_mobile_uniffi_contract_version()
|
||||||
|
if (bindings_contract_version != scaffolding_contract_version) {
|
||||||
|
throw RuntimeException("UniFFI contract version mismatch: try cleaning and rebuilding your project")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("UNUSED_PARAMETER")
|
||||||
|
private fun uniffiCheckApiChecksums(lib: _UniFFILib) {
|
||||||
|
if (lib.uniffi_mobile_checksum_func_auth() != 55720.toShort()) {
|
||||||
|
throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project")
|
||||||
|
}
|
||||||
|
if (lib.uniffi_mobile_checksum_func_myexample() != 65225.toShort()) {
|
||||||
|
throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Async support
|
||||||
|
// Async return type handlers
|
||||||
|
|
||||||
|
internal const val UNIFFI_RUST_FUTURE_POLL_READY = 0.toShort()
|
||||||
|
internal const val UNIFFI_RUST_FUTURE_POLL_MAYBE_READY = 1.toShort()
|
||||||
|
|
||||||
|
internal val uniffiContinuationHandleMap = UniFfiHandleMap<CancellableContinuation<Short>>()
|
||||||
|
|
||||||
|
// FFI type for Rust future continuations
|
||||||
|
internal object uniffiRustFutureContinuationCallback: UniFffiRustFutureContinuationCallbackType {
|
||||||
|
override fun callback(continuationHandle: USize, pollResult: Short) {
|
||||||
|
uniffiContinuationHandleMap.remove(continuationHandle)?.resume(pollResult)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun register(lib: _UniFFILib) {
|
||||||
|
lib.ffi_mobile_rust_future_continuation_callback_set(this)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal suspend fun<T, F, E: Exception> uniffiRustCallAsync(
|
||||||
|
rustFuture: Pointer,
|
||||||
|
pollFunc: (Pointer, USize) -> Unit,
|
||||||
|
completeFunc: (Pointer, RustCallStatus) -> F,
|
||||||
|
freeFunc: (Pointer) -> Unit,
|
||||||
|
liftFunc: (F) -> T,
|
||||||
|
errorHandler: CallStatusErrorHandler<E>
|
||||||
|
): T {
|
||||||
|
try {
|
||||||
|
do {
|
||||||
|
val pollResult = suspendCancellableCoroutine<Short> { continuation ->
|
||||||
|
pollFunc(
|
||||||
|
rustFuture,
|
||||||
|
uniffiContinuationHandleMap.insert(continuation)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} while (pollResult != UNIFFI_RUST_FUTURE_POLL_READY);
|
||||||
|
|
||||||
|
return liftFunc(
|
||||||
|
rustCallWithError(errorHandler, { status -> completeFunc(rustFuture, status) })
|
||||||
|
)
|
||||||
|
} finally {
|
||||||
|
freeFunc(rustFuture)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Public interface members begin here.
|
||||||
|
|
||||||
|
|
||||||
|
public object FfiConverterString: FfiConverter<String, RustBuffer.ByValue> {
|
||||||
|
// Note: we don't inherit from FfiConverterRustBuffer, because we use a
|
||||||
|
// special encoding when lowering/lifting. We can use `RustBuffer.len` to
|
||||||
|
// store our length and avoid writing it out to the buffer.
|
||||||
|
override fun lift(value: RustBuffer.ByValue): String {
|
||||||
|
try {
|
||||||
|
val byteArr = ByteArray(value.len)
|
||||||
|
value.asByteBuffer()!!.get(byteArr)
|
||||||
|
return byteArr.toString(Charsets.UTF_8)
|
||||||
|
} finally {
|
||||||
|
RustBuffer.free(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun read(buf: ByteBuffer): String {
|
||||||
|
val len = buf.getInt()
|
||||||
|
val byteArr = ByteArray(len)
|
||||||
|
buf.get(byteArr)
|
||||||
|
return byteArr.toString(Charsets.UTF_8)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun toUtf8(value: String): ByteBuffer {
|
||||||
|
// Make sure we don't have invalid UTF-16, check for lone surrogates.
|
||||||
|
return Charsets.UTF_8.newEncoder().run {
|
||||||
|
onMalformedInput(CodingErrorAction.REPORT)
|
||||||
|
encode(CharBuffer.wrap(value))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun lower(value: String): RustBuffer.ByValue {
|
||||||
|
val byteBuf = toUtf8(value)
|
||||||
|
// Ideally we'd pass these bytes to `ffi_bytebuffer_from_bytes`, but doing so would require us
|
||||||
|
// to copy them into a JNA `Memory`. So we might as well directly copy them into a `RustBuffer`.
|
||||||
|
val rbuf = RustBuffer.alloc(byteBuf.limit())
|
||||||
|
rbuf.asByteBuffer()!!.put(byteBuf)
|
||||||
|
return rbuf
|
||||||
|
}
|
||||||
|
|
||||||
|
// We aren't sure exactly how many bytes our string will be once it's UTF-8
|
||||||
|
// encoded. Allocate 3 bytes per UTF-16 code unit which will always be
|
||||||
|
// enough.
|
||||||
|
override fun allocationSize(value: String): Int {
|
||||||
|
val sizeForLength = 4
|
||||||
|
val sizeForString = value.length * 3
|
||||||
|
return sizeForLength + sizeForString
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun write(value: String, buf: ByteBuffer) {
|
||||||
|
val byteBuf = toUtf8(value)
|
||||||
|
buf.putInt(byteBuf.limit())
|
||||||
|
buf.put(byteBuf)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public object FfiConverterSequenceString: FfiConverterRustBuffer<List<String>> {
|
||||||
|
override fun read(buf: ByteBuffer): List<String> {
|
||||||
|
val len = buf.getInt()
|
||||||
|
return List<String>(len) {
|
||||||
|
FfiConverterString.read(buf)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun allocationSize(value: List<String>): Int {
|
||||||
|
val sizeForLength = 4
|
||||||
|
val sizeForItems = value.map { FfiConverterString.allocationSize(it) }.sum()
|
||||||
|
return sizeForLength + sizeForItems
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun write(value: List<String>, buf: ByteBuffer) {
|
||||||
|
buf.putInt(value.size)
|
||||||
|
value.forEach {
|
||||||
|
FfiConverterString.write(it, buf)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Suppress("ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE")
|
||||||
|
suspend fun `auth`(`url`: String, `secretKey`: String) : List<String> {
|
||||||
|
return uniffiRustCallAsync(
|
||||||
|
_UniFFILib.INSTANCE.uniffi_mobile_fn_func_auth(FfiConverterString.lower(`url`),FfiConverterString.lower(`secretKey`),),
|
||||||
|
{ future, continuation -> _UniFFILib.INSTANCE.ffi_mobile_rust_future_poll_rust_buffer(future, continuation) },
|
||||||
|
{ future, continuation -> _UniFFILib.INSTANCE.ffi_mobile_rust_future_complete_rust_buffer(future, continuation) },
|
||||||
|
{ future -> _UniFFILib.INSTANCE.ffi_mobile_rust_future_free_rust_buffer(future) },
|
||||||
|
// lift function
|
||||||
|
{ FfiConverterSequenceString.lift(it) },
|
||||||
|
// Error FFI converter
|
||||||
|
NullCallStatusErrorHandler,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun `myexample`(): List<String> {
|
||||||
|
return FfiConverterSequenceString.lift(
|
||||||
|
rustCall() { _status ->
|
||||||
|
_UniFFILib.INSTANCE.uniffi_mobile_fn_func_myexample(_status)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
BIN
android/src/main/jniLibs/arm64-v8a/libmobile.so
Executable file
BIN
android/src/main/jniLibs/armeabi-v7a/libmobile.so
Executable file
BIN
android/src/main/jniLibs/x86/libmobile.so
Executable file
BIN
android/src/main/jniLibs/x86_64/libmobile.so
Executable file
5
babel.config.js
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
module.exports = {
|
||||||
|
presets: [
|
||||||
|
['module:react-native-builder-bob/babel-preset', { modules: 'commonjs' }],
|
||||||
|
],
|
||||||
|
};
|
||||||
2
example/.bundle/config
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
BUNDLE_PATH: "vendor/bundle"
|
||||||
|
BUNDLE_FORCE_RUBY_PLATFORM: 1
|
||||||
1
example/.watchmanconfig
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{}
|
||||||
8
example/Gemfile
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
source 'https://rubygems.org'
|
||||||
|
|
||||||
|
# You may use http://rbenv.org/ or https://rvm.io/ to install and use this version
|
||||||
|
ruby ">= 2.6.10"
|
||||||
|
|
||||||
|
# Exclude problematic versions of cocoapods and activesupport that causes build failures.
|
||||||
|
gem 'cocoapods', '>= 1.13', '!= 1.15.0', '!= 1.15.1'
|
||||||
|
gem 'activesupport', '>= 6.1.7.5', '!= 7.1.0'
|
||||||
79
example/README.md
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
This is a new [**React Native**](https://reactnative.dev) project, bootstrapped using [`@react-native-community/cli`](https://github.com/react-native-community/cli).
|
||||||
|
|
||||||
|
# Getting Started
|
||||||
|
|
||||||
|
>**Note**: Make sure you have completed the [React Native - Environment Setup](https://reactnative.dev/docs/environment-setup) instructions till "Creating a new application" step, before proceeding.
|
||||||
|
|
||||||
|
## Step 1: Start the Metro Server
|
||||||
|
|
||||||
|
First, you will need to start **Metro**, the JavaScript _bundler_ that ships _with_ React Native.
|
||||||
|
|
||||||
|
To start Metro, run the following command from the _root_ of your React Native project:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# using npm
|
||||||
|
npm start
|
||||||
|
|
||||||
|
# OR using Yarn
|
||||||
|
yarn start
|
||||||
|
```
|
||||||
|
|
||||||
|
## Step 2: Start your Application
|
||||||
|
|
||||||
|
Let Metro Bundler run in its _own_ terminal. Open a _new_ terminal from the _root_ of your React Native project. Run the following command to start your _Android_ or _iOS_ app:
|
||||||
|
|
||||||
|
### For Android
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# using npm
|
||||||
|
npm run android
|
||||||
|
|
||||||
|
# OR using Yarn
|
||||||
|
yarn android
|
||||||
|
```
|
||||||
|
|
||||||
|
### For iOS
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# using npm
|
||||||
|
npm run ios
|
||||||
|
|
||||||
|
# OR using Yarn
|
||||||
|
yarn ios
|
||||||
|
```
|
||||||
|
|
||||||
|
If everything is set up _correctly_, you should see your new app running in your _Android Emulator_ or _iOS Simulator_ shortly provided you have set up your emulator/simulator correctly.
|
||||||
|
|
||||||
|
This is one way to run your app — you can also run it directly from within Android Studio and Xcode respectively.
|
||||||
|
|
||||||
|
## Step 3: Modifying your App
|
||||||
|
|
||||||
|
Now that you have successfully run the app, let's modify it.
|
||||||
|
|
||||||
|
1. Open `App.tsx` in your text editor of choice and edit some lines.
|
||||||
|
2. For **Android**: Press the <kbd>R</kbd> key twice or select **"Reload"** from the **Developer Menu** (<kbd>Ctrl</kbd> + <kbd>M</kbd> (on Window and Linux) or <kbd>Cmd ⌘</kbd> + <kbd>M</kbd> (on macOS)) to see your changes!
|
||||||
|
|
||||||
|
For **iOS**: Hit <kbd>Cmd ⌘</kbd> + <kbd>R</kbd> in your iOS Simulator to reload the app and see your changes!
|
||||||
|
|
||||||
|
## Congratulations! :tada:
|
||||||
|
|
||||||
|
You've successfully run and modified your React Native App. :partying_face:
|
||||||
|
|
||||||
|
### Now what?
|
||||||
|
|
||||||
|
- If you want to add this new React Native code to an existing application, check out the [Integration guide](https://reactnative.dev/docs/integration-with-existing-apps).
|
||||||
|
- If you're curious to learn more about React Native, check out the [Introduction to React Native](https://reactnative.dev/docs/getting-started).
|
||||||
|
|
||||||
|
# Troubleshooting
|
||||||
|
|
||||||
|
If you can't get this to work, see the [Troubleshooting](https://reactnative.dev/docs/troubleshooting) page.
|
||||||
|
|
||||||
|
# Learn More
|
||||||
|
|
||||||
|
To learn more about React Native, take a look at the following resources:
|
||||||
|
|
||||||
|
- [React Native Website](https://reactnative.dev) - learn more about React Native.
|
||||||
|
- [Getting Started](https://reactnative.dev/docs/environment-setup) - an **overview** of React Native and how setup your environment.
|
||||||
|
- [Learn the Basics](https://reactnative.dev/docs/getting-started) - a **guided tour** of the React Native **basics**.
|
||||||
|
- [Blog](https://reactnative.dev/blog) - read the latest official React Native **Blog** posts.
|
||||||
|
- [`@facebook/react-native`](https://github.com/facebook/react-native) - the Open Source; GitHub **repository** for React Native.
|
||||||
119
example/android/app/build.gradle
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
apply plugin: "com.android.application"
|
||||||
|
apply plugin: "org.jetbrains.kotlin.android"
|
||||||
|
apply plugin: "com.facebook.react"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is the configuration block to customize your React Native Android app.
|
||||||
|
* By default you don't need to apply any configuration, just uncomment the lines you need.
|
||||||
|
*/
|
||||||
|
react {
|
||||||
|
/* Folders */
|
||||||
|
// The root of your project, i.e. where "package.json" lives. Default is '../..'
|
||||||
|
// root = file("../../")
|
||||||
|
// The folder where the react-native NPM package is. Default is ../../node_modules/react-native
|
||||||
|
// reactNativeDir = file("../../node_modules/react-native")
|
||||||
|
// The folder where the react-native Codegen package is. Default is ../../node_modules/@react-native/codegen
|
||||||
|
// codegenDir = file("../../node_modules/@react-native/codegen")
|
||||||
|
// The cli.js file which is the React Native CLI entrypoint. Default is ../../node_modules/react-native/cli.js
|
||||||
|
// cliFile = file("../../node_modules/react-native/cli.js")
|
||||||
|
|
||||||
|
/* Variants */
|
||||||
|
// The list of variants to that are debuggable. For those we're going to
|
||||||
|
// skip the bundling of the JS bundle and the assets. By default is just 'debug'.
|
||||||
|
// If you add flavors like lite, prod, etc. you'll have to list your debuggableVariants.
|
||||||
|
// debuggableVariants = ["liteDebug", "prodDebug"]
|
||||||
|
|
||||||
|
/* Bundling */
|
||||||
|
// A list containing the node command and its flags. Default is just 'node'.
|
||||||
|
// nodeExecutableAndArgs = ["node"]
|
||||||
|
//
|
||||||
|
// The command to run when bundling. By default is 'bundle'
|
||||||
|
// bundleCommand = "ram-bundle"
|
||||||
|
//
|
||||||
|
// The path to the CLI configuration file. Default is empty.
|
||||||
|
// bundleConfig = file(../rn-cli.config.js)
|
||||||
|
//
|
||||||
|
// The name of the generated asset file containing your JS bundle
|
||||||
|
// bundleAssetName = "MyApplication.android.bundle"
|
||||||
|
//
|
||||||
|
// The entry file for bundle generation. Default is 'index.android.js' or 'index.js'
|
||||||
|
// entryFile = file("../js/MyApplication.android.js")
|
||||||
|
//
|
||||||
|
// A list of extra flags to pass to the 'bundle' commands.
|
||||||
|
// See https://github.com/react-native-community/cli/blob/main/docs/commands.md#bundle
|
||||||
|
// extraPackagerArgs = []
|
||||||
|
|
||||||
|
/* Hermes Commands */
|
||||||
|
// The hermes compiler command to run. By default it is 'hermesc'
|
||||||
|
// hermesCommand = "$rootDir/my-custom-hermesc/bin/hermesc"
|
||||||
|
//
|
||||||
|
// The list of flags to pass to the Hermes compiler. By default is "-O", "-output-source-map"
|
||||||
|
// hermesFlags = ["-O", "-output-source-map"]
|
||||||
|
|
||||||
|
/* Autolinking */
|
||||||
|
autolinkLibrariesWithApp()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set this to true to Run Proguard on Release builds to minify the Java bytecode.
|
||||||
|
*/
|
||||||
|
def enableProguardInReleaseBuilds = false
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The preferred build flavor of JavaScriptCore (JSC)
|
||||||
|
*
|
||||||
|
* For example, to use the international variant, you can use:
|
||||||
|
* `def jscFlavor = 'org.webkit:android-jsc-intl:+'`
|
||||||
|
*
|
||||||
|
* The international variant includes ICU i18n library and necessary data
|
||||||
|
* allowing to use e.g. `Date.toLocaleString` and `String.localeCompare` that
|
||||||
|
* give correct results when using with locales other than en-US. Note that
|
||||||
|
* this variant is about 6MiB larger per architecture than default.
|
||||||
|
*/
|
||||||
|
def jscFlavor = 'org.webkit:android-jsc:+'
|
||||||
|
|
||||||
|
android {
|
||||||
|
ndkVersion rootProject.ext.ndkVersion
|
||||||
|
buildToolsVersion rootProject.ext.buildToolsVersion
|
||||||
|
compileSdk rootProject.ext.compileSdkVersion
|
||||||
|
|
||||||
|
namespace "pubky.example"
|
||||||
|
defaultConfig {
|
||||||
|
applicationId "pubky.example"
|
||||||
|
minSdkVersion rootProject.ext.minSdkVersion
|
||||||
|
targetSdkVersion rootProject.ext.targetSdkVersion
|
||||||
|
versionCode 1
|
||||||
|
versionName "1.0"
|
||||||
|
}
|
||||||
|
signingConfigs {
|
||||||
|
debug {
|
||||||
|
storeFile file('debug.keystore')
|
||||||
|
storePassword 'android'
|
||||||
|
keyAlias 'androiddebugkey'
|
||||||
|
keyPassword 'android'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
buildTypes {
|
||||||
|
debug {
|
||||||
|
signingConfig signingConfigs.debug
|
||||||
|
}
|
||||||
|
release {
|
||||||
|
// Caution! In production, you need to generate your own keystore file.
|
||||||
|
// see https://reactnative.dev/docs/signed-apk-android.
|
||||||
|
signingConfig signingConfigs.debug
|
||||||
|
minifyEnabled enableProguardInReleaseBuilds
|
||||||
|
proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
// The version of react-native is set by the React Native Gradle Plugin
|
||||||
|
implementation("com.facebook.react:react-android")
|
||||||
|
|
||||||
|
if (hermesEnabled.toBoolean()) {
|
||||||
|
implementation("com.facebook.react:hermes-android")
|
||||||
|
} else {
|
||||||
|
implementation jscFlavor
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
example/android/app/debug.keystore
Normal file
10
example/android/app/proguard-rules.pro
vendored
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
# Add project specific ProGuard rules here.
|
||||||
|
# By default, the flags in this file are appended to flags specified
|
||||||
|
# in /usr/local/Cellar/android-sdk/24.3.3/tools/proguard/proguard-android.txt
|
||||||
|
# You can edit the include path and order by changing the proguardFiles
|
||||||
|
# directive in build.gradle.
|
||||||
|
#
|
||||||
|
# For more details, see
|
||||||
|
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||||
|
|
||||||
|
# Add any project specific keep options here:
|
||||||
9
example/android/app/src/debug/AndroidManifest.xml
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools">
|
||||||
|
|
||||||
|
<application
|
||||||
|
android:usesCleartextTraffic="true"
|
||||||
|
tools:targetApi="28"
|
||||||
|
tools:ignore="GoogleAppIndexingWarning"/>
|
||||||
|
</manifest>
|
||||||
26
example/android/app/src/main/AndroidManifest.xml
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
|
||||||
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
|
|
||||||
|
<application
|
||||||
|
android:name=".MainApplication"
|
||||||
|
android:label="@string/app_name"
|
||||||
|
android:icon="@mipmap/ic_launcher"
|
||||||
|
android:roundIcon="@mipmap/ic_launcher_round"
|
||||||
|
android:allowBackup="false"
|
||||||
|
android:theme="@style/AppTheme"
|
||||||
|
android:supportsRtl="true">
|
||||||
|
<activity
|
||||||
|
android:name=".MainActivity"
|
||||||
|
android:label="@string/app_name"
|
||||||
|
android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|screenSize|smallestScreenSize|uiMode"
|
||||||
|
android:launchMode="singleTask"
|
||||||
|
android:windowSoftInputMode="adjustResize"
|
||||||
|
android:exported="true">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
|
</intent-filter>
|
||||||
|
</activity>
|
||||||
|
</application>
|
||||||
|
</manifest>
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package pubky.example
|
||||||
|
|
||||||
|
import com.facebook.react.ReactActivity
|
||||||
|
import com.facebook.react.ReactActivityDelegate
|
||||||
|
import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.fabricEnabled
|
||||||
|
import com.facebook.react.defaults.DefaultReactActivityDelegate
|
||||||
|
|
||||||
|
class MainActivity : ReactActivity() {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the name of the main component registered from JavaScript. This is used to schedule
|
||||||
|
* rendering of the component.
|
||||||
|
*/
|
||||||
|
override fun getMainComponentName(): String = "PubkyExample"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the instance of the [ReactActivityDelegate]. We use [DefaultReactActivityDelegate]
|
||||||
|
* which allows you to enable New Architecture with a single boolean flags [fabricEnabled]
|
||||||
|
*/
|
||||||
|
override fun createReactActivityDelegate(): ReactActivityDelegate =
|
||||||
|
DefaultReactActivityDelegate(this, mainComponentName, fabricEnabled)
|
||||||
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
package pubky.example
|
||||||
|
|
||||||
|
import android.app.Application
|
||||||
|
import com.facebook.react.PackageList
|
||||||
|
import com.facebook.react.ReactApplication
|
||||||
|
import com.facebook.react.ReactHost
|
||||||
|
import com.facebook.react.ReactNativeHost
|
||||||
|
import com.facebook.react.ReactPackage
|
||||||
|
import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.load
|
||||||
|
import com.facebook.react.defaults.DefaultReactHost.getDefaultReactHost
|
||||||
|
import com.facebook.react.defaults.DefaultReactNativeHost
|
||||||
|
import com.facebook.soloader.SoLoader
|
||||||
|
|
||||||
|
class MainApplication : Application(), ReactApplication {
|
||||||
|
|
||||||
|
override val reactNativeHost: ReactNativeHost =
|
||||||
|
object : DefaultReactNativeHost(this) {
|
||||||
|
override fun getPackages(): List<ReactPackage> =
|
||||||
|
PackageList(this).packages.apply {
|
||||||
|
// Packages that cannot be autolinked yet can be added manually here, for example:
|
||||||
|
// add(MyReactNativePackage())
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getJSMainModuleName(): String = "index"
|
||||||
|
|
||||||
|
override fun getUseDeveloperSupport(): Boolean = BuildConfig.DEBUG
|
||||||
|
|
||||||
|
override val isNewArchEnabled: Boolean = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED
|
||||||
|
override val isHermesEnabled: Boolean = BuildConfig.IS_HERMES_ENABLED
|
||||||
|
}
|
||||||
|
|
||||||
|
override val reactHost: ReactHost
|
||||||
|
get() = getDefaultReactHost(applicationContext, reactNativeHost)
|
||||||
|
|
||||||
|
override fun onCreate() {
|
||||||
|
super.onCreate()
|
||||||
|
SoLoader.init(this, false)
|
||||||
|
if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
|
||||||
|
// If you opted-in for the New Architecture, we load the native entry point for this app.
|
||||||
|
load()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Copyright (C) 2014 The Android Open Source Project
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
-->
|
||||||
|
<inset xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:insetLeft="@dimen/abc_edit_text_inset_horizontal_material"
|
||||||
|
android:insetRight="@dimen/abc_edit_text_inset_horizontal_material"
|
||||||
|
android:insetTop="@dimen/abc_edit_text_inset_top_material"
|
||||||
|
android:insetBottom="@dimen/abc_edit_text_inset_bottom_material"
|
||||||
|
>
|
||||||
|
|
||||||
|
<selector>
|
||||||
|
<!--
|
||||||
|
This file is a copy of abc_edit_text_material (https://bit.ly/3k8fX7I).
|
||||||
|
The item below with state_pressed="false" and state_focused="false" causes a NullPointerException.
|
||||||
|
NullPointerException:tempt to invoke virtual method 'android.graphics.drawable.Drawable android.graphics.drawable.Drawable$ConstantState.newDrawable(android.content.res.Resources)'
|
||||||
|
|
||||||
|
<item android:state_pressed="false" android:state_focused="false" android:drawable="@drawable/abc_textfield_default_mtrl_alpha"/>
|
||||||
|
|
||||||
|
For more info, see https://bit.ly/3CdLStv (react-native/pull/29452) and https://bit.ly/3nxOMoR.
|
||||||
|
-->
|
||||||
|
<item android:state_enabled="false" android:drawable="@drawable/abc_textfield_default_mtrl_alpha"/>
|
||||||
|
<item android:drawable="@drawable/abc_textfield_activated_mtrl_alpha"/>
|
||||||
|
</selector>
|
||||||
|
|
||||||
|
</inset>
|
||||||
BIN
example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 4.9 KiB |
BIN
example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 2.8 KiB |
BIN
example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 4.5 KiB |
|
After Width: | Height: | Size: 6.9 KiB |
BIN
example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 6.3 KiB |
|
After Width: | Height: | Size: 10 KiB |
BIN
example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 9.0 KiB |
|
After Width: | Height: | Size: 15 KiB |
3
example/android/app/src/main/res/values/strings.xml
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
<resources>
|
||||||
|
<string name="app_name">PubkyExample</string>
|
||||||
|
</resources>
|
||||||
9
example/android/app/src/main/res/values/styles.xml
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<resources>
|
||||||
|
|
||||||
|
<!-- Base application theme. -->
|
||||||
|
<style name="AppTheme" parent="Theme.AppCompat.DayNight.NoActionBar">
|
||||||
|
<!-- Customize your theme here. -->
|
||||||
|
<item name="android:editTextBackground">@drawable/rn_edit_text_material</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
|
</resources>
|
||||||
21
example/android/build.gradle
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
buildscript {
|
||||||
|
ext {
|
||||||
|
buildToolsVersion = "34.0.0"
|
||||||
|
minSdkVersion = 23
|
||||||
|
compileSdkVersion = 34
|
||||||
|
targetSdkVersion = 34
|
||||||
|
ndkVersion = "26.1.10909125"
|
||||||
|
kotlinVersion = "1.9.24"
|
||||||
|
}
|
||||||
|
repositories {
|
||||||
|
google()
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
dependencies {
|
||||||
|
classpath("com.android.tools.build:gradle")
|
||||||
|
classpath("com.facebook.react:react-native-gradle-plugin")
|
||||||
|
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
apply plugin: "com.facebook.react.rootproject"
|
||||||
39
example/android/gradle.properties
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
# Project-wide Gradle settings.
|
||||||
|
|
||||||
|
# IDE (e.g. Android Studio) users:
|
||||||
|
# Gradle settings configured through the IDE *will override*
|
||||||
|
# any settings specified in this file.
|
||||||
|
|
||||||
|
# For more details on how to configure your build environment visit
|
||||||
|
# http://www.gradle.org/docs/current/userguide/build_environment.html
|
||||||
|
|
||||||
|
# Specifies the JVM arguments used for the daemon process.
|
||||||
|
# The setting is particularly useful for tweaking memory settings.
|
||||||
|
# Default value: -Xmx512m -XX:MaxMetaspaceSize=256m
|
||||||
|
org.gradle.jvmargs=-Xmx2048m -XX:MaxMetaspaceSize=512m
|
||||||
|
|
||||||
|
# When configured, Gradle will run in incubating parallel mode.
|
||||||
|
# This option should only be used with decoupled projects. More details, visit
|
||||||
|
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
|
||||||
|
# org.gradle.parallel=true
|
||||||
|
|
||||||
|
# AndroidX package structure to make it clearer which packages are bundled with the
|
||||||
|
# Android operating system, and which are packaged with your app's APK
|
||||||
|
# https://developer.android.com/topic/libraries/support-library/androidx-rn
|
||||||
|
android.useAndroidX=true
|
||||||
|
|
||||||
|
# Use this property to specify which architecture you want to build.
|
||||||
|
# You can also override it from the CLI using
|
||||||
|
# ./gradlew <task> -PreactNativeArchitectures=x86_64
|
||||||
|
reactNativeArchitectures=armeabi-v7a,arm64-v8a,x86,x86_64
|
||||||
|
|
||||||
|
# Use this property to enable support to the new architecture.
|
||||||
|
# This will allow you to use TurboModules and the Fabric render in
|
||||||
|
# your application. You should enable this flag either if you want
|
||||||
|
# to write custom TurboModules/Fabric components OR use libraries that
|
||||||
|
# are providing them.
|
||||||
|
newArchEnabled=false
|
||||||
|
|
||||||
|
# Use this property to enable or disable the Hermes JS engine.
|
||||||
|
# If set to false, you will be using JSC instead.
|
||||||
|
hermesEnabled=true
|
||||||
BIN
example/android/gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
7
example/android/gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
distributionBase=GRADLE_USER_HOME
|
||||||
|
distributionPath=wrapper/dists
|
||||||
|
distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-all.zip
|
||||||
|
networkTimeout=10000
|
||||||
|
validateDistributionUrl=true
|
||||||
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
|
zipStorePath=wrapper/dists
|
||||||
249
example/android/gradlew
vendored
Executable file
@@ -0,0 +1,249 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
#
|
||||||
|
# Copyright © 2015-2021 the original authors.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
#
|
||||||
|
|
||||||
|
##############################################################################
|
||||||
|
#
|
||||||
|
# Gradle start up script for POSIX generated by Gradle.
|
||||||
|
#
|
||||||
|
# Important for running:
|
||||||
|
#
|
||||||
|
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
|
||||||
|
# noncompliant, but you have some other compliant shell such as ksh or
|
||||||
|
# bash, then to run this script, type that shell name before the whole
|
||||||
|
# command line, like:
|
||||||
|
#
|
||||||
|
# ksh Gradle
|
||||||
|
#
|
||||||
|
# Busybox and similar reduced shells will NOT work, because this script
|
||||||
|
# requires all of these POSIX shell features:
|
||||||
|
# * functions;
|
||||||
|
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
|
||||||
|
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
|
||||||
|
# * compound commands having a testable exit status, especially «case»;
|
||||||
|
# * various built-in commands including «command», «set», and «ulimit».
|
||||||
|
#
|
||||||
|
# Important for patching:
|
||||||
|
#
|
||||||
|
# (2) This script targets any POSIX shell, so it avoids extensions provided
|
||||||
|
# by Bash, Ksh, etc; in particular arrays are avoided.
|
||||||
|
#
|
||||||
|
# The "traditional" practice of packing multiple parameters into a
|
||||||
|
# space-separated string is a well documented source of bugs and security
|
||||||
|
# problems, so this is (mostly) avoided, by progressively accumulating
|
||||||
|
# options in "$@", and eventually passing that to Java.
|
||||||
|
#
|
||||||
|
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
|
||||||
|
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
|
||||||
|
# see the in-line comments for details.
|
||||||
|
#
|
||||||
|
# There are tweaks for specific operating systems such as AIX, CygWin,
|
||||||
|
# Darwin, MinGW, and NonStop.
|
||||||
|
#
|
||||||
|
# (3) This script is generated from the Groovy template
|
||||||
|
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||||
|
# within the Gradle project.
|
||||||
|
#
|
||||||
|
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||||
|
#
|
||||||
|
##############################################################################
|
||||||
|
|
||||||
|
# Attempt to set APP_HOME
|
||||||
|
|
||||||
|
# Resolve links: $0 may be a link
|
||||||
|
app_path=$0
|
||||||
|
|
||||||
|
# Need this for daisy-chained symlinks.
|
||||||
|
while
|
||||||
|
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
|
||||||
|
[ -h "$app_path" ]
|
||||||
|
do
|
||||||
|
ls=$( ls -ld "$app_path" )
|
||||||
|
link=${ls#*' -> '}
|
||||||
|
case $link in #(
|
||||||
|
/*) app_path=$link ;; #(
|
||||||
|
*) app_path=$APP_HOME$link ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
# This is normally unused
|
||||||
|
# shellcheck disable=SC2034
|
||||||
|
APP_BASE_NAME=${0##*/}
|
||||||
|
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
|
||||||
|
APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
|
||||||
|
|
||||||
|
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||||
|
MAX_FD=maximum
|
||||||
|
|
||||||
|
warn () {
|
||||||
|
echo "$*"
|
||||||
|
} >&2
|
||||||
|
|
||||||
|
die () {
|
||||||
|
echo
|
||||||
|
echo "$*"
|
||||||
|
echo
|
||||||
|
exit 1
|
||||||
|
} >&2
|
||||||
|
|
||||||
|
# OS specific support (must be 'true' or 'false').
|
||||||
|
cygwin=false
|
||||||
|
msys=false
|
||||||
|
darwin=false
|
||||||
|
nonstop=false
|
||||||
|
case "$( uname )" in #(
|
||||||
|
CYGWIN* ) cygwin=true ;; #(
|
||||||
|
Darwin* ) darwin=true ;; #(
|
||||||
|
MSYS* | MINGW* ) msys=true ;; #(
|
||||||
|
NONSTOP* ) nonstop=true ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||||
|
|
||||||
|
|
||||||
|
# Determine the Java command to use to start the JVM.
|
||||||
|
if [ -n "$JAVA_HOME" ] ; then
|
||||||
|
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||||
|
# IBM's JDK on AIX uses strange locations for the executables
|
||||||
|
JAVACMD=$JAVA_HOME/jre/sh/java
|
||||||
|
else
|
||||||
|
JAVACMD=$JAVA_HOME/bin/java
|
||||||
|
fi
|
||||||
|
if [ ! -x "$JAVACMD" ] ; then
|
||||||
|
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||||
|
|
||||||
|
Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
location of your Java installation."
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
JAVACMD=java
|
||||||
|
if ! command -v java >/dev/null 2>&1
|
||||||
|
then
|
||||||
|
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||||
|
|
||||||
|
Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
location of your Java installation."
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Increase the maximum file descriptors if we can.
|
||||||
|
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
||||||
|
case $MAX_FD in #(
|
||||||
|
max*)
|
||||||
|
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
|
||||||
|
# shellcheck disable=SC2039,SC3045
|
||||||
|
MAX_FD=$( ulimit -H -n ) ||
|
||||||
|
warn "Could not query maximum file descriptor limit"
|
||||||
|
esac
|
||||||
|
case $MAX_FD in #(
|
||||||
|
'' | soft) :;; #(
|
||||||
|
*)
|
||||||
|
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
|
||||||
|
# shellcheck disable=SC2039,SC3045
|
||||||
|
ulimit -n "$MAX_FD" ||
|
||||||
|
warn "Could not set maximum file descriptor limit to $MAX_FD"
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Collect all arguments for the java command, stacking in reverse order:
|
||||||
|
# * args from the command line
|
||||||
|
# * the main class name
|
||||||
|
# * -classpath
|
||||||
|
# * -D...appname settings
|
||||||
|
# * --module-path (only if needed)
|
||||||
|
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
|
||||||
|
|
||||||
|
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||||
|
if "$cygwin" || "$msys" ; then
|
||||||
|
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
|
||||||
|
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
|
||||||
|
|
||||||
|
JAVACMD=$( cygpath --unix "$JAVACMD" )
|
||||||
|
|
||||||
|
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||||
|
for arg do
|
||||||
|
if
|
||||||
|
case $arg in #(
|
||||||
|
-*) false ;; # don't mess with options #(
|
||||||
|
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
|
||||||
|
[ -e "$t" ] ;; #(
|
||||||
|
*) false ;;
|
||||||
|
esac
|
||||||
|
then
|
||||||
|
arg=$( cygpath --path --ignore --mixed "$arg" )
|
||||||
|
fi
|
||||||
|
# Roll the args list around exactly as many times as the number of
|
||||||
|
# args, so each arg winds up back in the position where it started, but
|
||||||
|
# possibly modified.
|
||||||
|
#
|
||||||
|
# NB: a `for` loop captures its iteration list before it begins, so
|
||||||
|
# changing the positional parameters here affects neither the number of
|
||||||
|
# iterations, nor the values presented in `arg`.
|
||||||
|
shift # remove old arg
|
||||||
|
set -- "$@" "$arg" # push replacement arg
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
|
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||||
|
|
||||||
|
# Collect all arguments for the java command:
|
||||||
|
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
|
||||||
|
# and any embedded shellness will be escaped.
|
||||||
|
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
|
||||||
|
# treated as '${Hostname}' itself on the command line.
|
||||||
|
|
||||||
|
set -- \
|
||||||
|
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
||||||
|
-classpath "$CLASSPATH" \
|
||||||
|
org.gradle.wrapper.GradleWrapperMain \
|
||||||
|
"$@"
|
||||||
|
|
||||||
|
# Stop when "xargs" is not available.
|
||||||
|
if ! command -v xargs >/dev/null 2>&1
|
||||||
|
then
|
||||||
|
die "xargs is not available"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Use "xargs" to parse quoted args.
|
||||||
|
#
|
||||||
|
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
|
||||||
|
#
|
||||||
|
# In Bash we could simply go:
|
||||||
|
#
|
||||||
|
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
|
||||||
|
# set -- "${ARGS[@]}" "$@"
|
||||||
|
#
|
||||||
|
# but POSIX shell has neither arrays nor command substitution, so instead we
|
||||||
|
# post-process each arg (as a line of input to sed) to backslash-escape any
|
||||||
|
# character that might be a shell metacharacter, then use eval to reverse
|
||||||
|
# that process (while maintaining the separation between arguments), and wrap
|
||||||
|
# the whole thing up as a single "set" statement.
|
||||||
|
#
|
||||||
|
# This will of course break if any of these variables contains a newline or
|
||||||
|
# an unmatched quote.
|
||||||
|
#
|
||||||
|
|
||||||
|
eval "set -- $(
|
||||||
|
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
|
||||||
|
xargs -n1 |
|
||||||
|
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
|
||||||
|
tr '\n' ' '
|
||||||
|
)" '"$@"'
|
||||||
|
|
||||||
|
exec "$JAVACMD" "$@"
|
||||||
92
example/android/gradlew.bat
vendored
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
@rem
|
||||||
|
@rem Copyright 2015 the original author or authors.
|
||||||
|
@rem
|
||||||
|
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
@rem you may not use this file except in compliance with the License.
|
||||||
|
@rem You may obtain a copy of the License at
|
||||||
|
@rem
|
||||||
|
@rem https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
@rem
|
||||||
|
@rem Unless required by applicable law or agreed to in writing, software
|
||||||
|
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
@rem See the License for the specific language governing permissions and
|
||||||
|
@rem limitations under the License.
|
||||||
|
@rem
|
||||||
|
|
||||||
|
@if "%DEBUG%"=="" @echo off
|
||||||
|
@rem ##########################################################################
|
||||||
|
@rem
|
||||||
|
@rem Gradle startup script for Windows
|
||||||
|
@rem
|
||||||
|
@rem ##########################################################################
|
||||||
|
|
||||||
|
@rem Set local scope for the variables with windows NT shell
|
||||||
|
if "%OS%"=="Windows_NT" setlocal
|
||||||
|
|
||||||
|
set DIRNAME=%~dp0
|
||||||
|
if "%DIRNAME%"=="" set DIRNAME=.
|
||||||
|
@rem This is normally unused
|
||||||
|
set APP_BASE_NAME=%~n0
|
||||||
|
set APP_HOME=%DIRNAME%
|
||||||
|
|
||||||
|
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
||||||
|
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
||||||
|
|
||||||
|
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
|
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||||
|
|
||||||
|
@rem Find java.exe
|
||||||
|
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||||
|
|
||||||
|
set JAVA_EXE=java.exe
|
||||||
|
%JAVA_EXE% -version >NUL 2>&1
|
||||||
|
if %ERRORLEVEL% equ 0 goto execute
|
||||||
|
|
||||||
|
echo. 1>&2
|
||||||
|
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
|
||||||
|
echo. 1>&2
|
||||||
|
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||||
|
echo location of your Java installation. 1>&2
|
||||||
|
|
||||||
|
goto fail
|
||||||
|
|
||||||
|
:findJavaFromJavaHome
|
||||||
|
set JAVA_HOME=%JAVA_HOME:"=%
|
||||||
|
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||||
|
|
||||||
|
if exist "%JAVA_EXE%" goto execute
|
||||||
|
|
||||||
|
echo. 1>&2
|
||||||
|
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
|
||||||
|
echo. 1>&2
|
||||||
|
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||||
|
echo location of your Java installation. 1>&2
|
||||||
|
|
||||||
|
goto fail
|
||||||
|
|
||||||
|
:execute
|
||||||
|
@rem Setup the command line
|
||||||
|
|
||||||
|
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||||
|
|
||||||
|
|
||||||
|
@rem Execute Gradle
|
||||||
|
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
|
||||||
|
|
||||||
|
:end
|
||||||
|
@rem End local scope for the variables with windows NT shell
|
||||||
|
if %ERRORLEVEL% equ 0 goto mainEnd
|
||||||
|
|
||||||
|
:fail
|
||||||
|
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||||
|
rem the _cmd.exe /c_ return code!
|
||||||
|
set EXIT_CODE=%ERRORLEVEL%
|
||||||
|
if %EXIT_CODE% equ 0 set EXIT_CODE=1
|
||||||
|
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
|
||||||
|
exit /b %EXIT_CODE%
|
||||||
|
|
||||||
|
:mainEnd
|
||||||
|
if "%OS%"=="Windows_NT" endlocal
|
||||||
|
|
||||||
|
:omega
|
||||||
6
example/android/settings.gradle
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
pluginManagement { includeBuild("../node_modules/@react-native/gradle-plugin") }
|
||||||
|
plugins { id("com.facebook.react.settings") }
|
||||||
|
extensions.configure(com.facebook.react.ReactSettingsExtension){ ex -> ex.autolinkLibrariesFromCommand() }
|
||||||
|
rootProject.name = 'pubky.example'
|
||||||
|
include ':app'
|
||||||
|
includeBuild('../node_modules/@react-native/gradle-plugin')
|
||||||
4
example/app.json
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"name": "PubkyExample",
|
||||||
|
"displayName": "PubkyExample"
|
||||||
|
}
|
||||||
12
example/babel.config.js
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
const path = require('path');
|
||||||
|
const { getConfig } = require('react-native-builder-bob/babel-config');
|
||||||
|
const pkg = require('../package.json');
|
||||||
|
|
||||||
|
const root = path.resolve(__dirname, '..');
|
||||||
|
|
||||||
|
module.exports = getConfig(
|
||||||
|
{
|
||||||
|
presets: ['module:@react-native/babel-preset'],
|
||||||
|
},
|
||||||
|
{ root, pkg }
|
||||||
|
);
|
||||||
5
example/index.js
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
import { AppRegistry } from 'react-native';
|
||||||
|
import App from './src/App';
|
||||||
|
import { name as appName } from './app.json';
|
||||||
|
|
||||||
|
AppRegistry.registerComponent(appName, () => App);
|
||||||
11
example/ios/.xcode.env
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
# This `.xcode.env` file is versioned and is used to source the environment
|
||||||
|
# used when running script phases inside Xcode.
|
||||||
|
# To customize your local environment, you can create an `.xcode.env.local`
|
||||||
|
# file that is not versioned.
|
||||||
|
|
||||||
|
# NODE_BINARY variable contains the PATH to the node executable.
|
||||||
|
#
|
||||||
|
# Customize the NODE_BINARY variable here.
|
||||||
|
# For example, to use nvm with brew, add the following line
|
||||||
|
# . "$(brew --prefix nvm)/nvm.sh" --no-use
|
||||||
|
export NODE_BINARY=$(command -v node)
|
||||||
1
example/ios/.xcode.env.local
Normal file
@@ -0,0 +1 @@
|
|||||||
|
export NODE_BINARY=/Users/coreyphillips/.nvm/versions/node/v20.14.0/bin/node
|
||||||
6
example/ios/File.swift
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
//
|
||||||
|
// File.swift
|
||||||
|
// PubkyExample
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
40
example/ios/Podfile
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
# Resolve react_native_pods.rb with node to allow for hoisting
|
||||||
|
require Pod::Executable.execute_command('node', ['-p',
|
||||||
|
'require.resolve(
|
||||||
|
"react-native/scripts/react_native_pods.rb",
|
||||||
|
{paths: [process.argv[1]]},
|
||||||
|
)', __dir__]).strip
|
||||||
|
|
||||||
|
platform :ios, min_ios_version_supported
|
||||||
|
prepare_react_native_project!
|
||||||
|
|
||||||
|
linkage = ENV['USE_FRAMEWORKS']
|
||||||
|
if linkage != nil
|
||||||
|
Pod::UI.puts "Configuring Pod with #{linkage}ally linked Frameworks".green
|
||||||
|
use_frameworks! :linkage => linkage.to_sym
|
||||||
|
end
|
||||||
|
|
||||||
|
target 'PubkyExample' do
|
||||||
|
config = use_native_modules!
|
||||||
|
|
||||||
|
use_react_native!(
|
||||||
|
:path => config[:reactNativePath],
|
||||||
|
# An absolute path to your application root.
|
||||||
|
:app_path => "#{Pod::Config.instance.installation_root}/.."
|
||||||
|
)
|
||||||
|
|
||||||
|
target 'PubkyExampleTests' do
|
||||||
|
inherit! :complete
|
||||||
|
# Pods for testing
|
||||||
|
end
|
||||||
|
|
||||||
|
post_install do |installer|
|
||||||
|
# https://github.com/facebook/react-native/blob/main/packages/react-native/scripts/react_native_pods.rb#L197-L202
|
||||||
|
react_native_post_install(
|
||||||
|
installer,
|
||||||
|
config[:reactNativePath],
|
||||||
|
:mac_catalyst_enabled => false,
|
||||||
|
# :ccache_enabled => true
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
1792
example/ios/Podfile.lock
Normal file
3
example/ios/PubkyExample-Bridging-Header.h
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
//
|
||||||
|
// Use this file to import your target's public headers that you would like to expose to Swift.
|
||||||
|
//
|
||||||
713
example/ios/PubkyExample.xcodeproj/project.pbxproj
Normal file
@@ -0,0 +1,713 @@
|
|||||||
|
// !$*UTF8*$!
|
||||||
|
{
|
||||||
|
archiveVersion = 1;
|
||||||
|
classes = {
|
||||||
|
};
|
||||||
|
objectVersion = 54;
|
||||||
|
objects = {
|
||||||
|
|
||||||
|
/* Begin PBXBuildFile section */
|
||||||
|
00E356F31AD99517003FC87E /* PubkyExampleTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 00E356F21AD99517003FC87E /* PubkyExampleTests.m */; };
|
||||||
|
0C80B921A6F3F58F76C31292 /* libPods-PubkyExample.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5DCACB8F33CDC322A6C60F78 /* libPods-PubkyExample.a */; };
|
||||||
|
13B07FBC1A68108700A75B9A /* AppDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.mm */; };
|
||||||
|
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
|
||||||
|
13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
|
||||||
|
7699B88040F8A987B510C191 /* libPods-PubkyExample-PubkyExampleTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 19F6CBCC0A4E27FBF8BF4A61 /* libPods-PubkyExample-PubkyExampleTests.a */; };
|
||||||
|
81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */; };
|
||||||
|
B2A00F0E44E958DA013ABFD6 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = AF7D486B6E71CFB714642CFB /* PrivacyInfo.xcprivacy */; };
|
||||||
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
|
/* Begin PBXContainerItemProxy section */
|
||||||
|
00E356F41AD99517003FC87E /* PBXContainerItemProxy */ = {
|
||||||
|
isa = PBXContainerItemProxy;
|
||||||
|
containerPortal = 83CBB9F71A601CBA00E9B192 /* Project object */;
|
||||||
|
proxyType = 1;
|
||||||
|
remoteGlobalIDString = 13B07F861A680F5B00A75B9A;
|
||||||
|
remoteInfo = PubkyExample;
|
||||||
|
};
|
||||||
|
/* End PBXContainerItemProxy section */
|
||||||
|
|
||||||
|
/* Begin PBXFileReference section */
|
||||||
|
00E356EE1AD99517003FC87E /* PubkyExampleTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = PubkyExampleTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
|
00E356F11AD99517003FC87E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||||
|
00E356F21AD99517003FC87E /* PubkyExampleTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = PubkyExampleTests.m; sourceTree = "<group>"; };
|
||||||
|
13B07F961A680F5B00A75B9A /* PubkyExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = PubkyExample.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
|
13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = PubkyExample/AppDelegate.h; sourceTree = "<group>"; };
|
||||||
|
13B07FB01A68108700A75B9A /* AppDelegate.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = AppDelegate.mm; path = PubkyExample/AppDelegate.mm; sourceTree = "<group>"; };
|
||||||
|
13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = PubkyExample/Images.xcassets; sourceTree = "<group>"; };
|
||||||
|
13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = PubkyExample/Info.plist; sourceTree = "<group>"; };
|
||||||
|
13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = PubkyExample/main.m; sourceTree = "<group>"; };
|
||||||
|
13B07FB81A68108700A75B9A /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = PrivacyInfo.xcprivacy; path = PubkyExample/PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
|
||||||
|
19F6CBCC0A4E27FBF8BF4A61 /* libPods-PubkyExample-PubkyExampleTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-PubkyExample-PubkyExampleTests.a"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
|
3B4392A12AC88292D35C810B /* Pods-PubkyExample.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PubkyExample.debug.xcconfig"; path = "Target Support Files/Pods-PubkyExample/Pods-PubkyExample.debug.xcconfig"; sourceTree = "<group>"; };
|
||||||
|
5709B34CF0A7D63546082F79 /* Pods-PubkyExample.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PubkyExample.release.xcconfig"; path = "Target Support Files/Pods-PubkyExample/Pods-PubkyExample.release.xcconfig"; sourceTree = "<group>"; };
|
||||||
|
5B7EB9410499542E8C5724F5 /* Pods-PubkyExample-PubkyExampleTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PubkyExample-PubkyExampleTests.debug.xcconfig"; path = "Target Support Files/Pods-PubkyExample-PubkyExampleTests/Pods-PubkyExample-PubkyExampleTests.debug.xcconfig"; sourceTree = "<group>"; };
|
||||||
|
5DCACB8F33CDC322A6C60F78 /* libPods-PubkyExample.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-PubkyExample.a"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
|
81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = LaunchScreen.storyboard; path = PubkyExample/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
||||||
|
89C6BE57DB24E9ADA2F236DE /* Pods-PubkyExample-PubkyExampleTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PubkyExample-PubkyExampleTests.release.xcconfig"; path = "Target Support Files/Pods-PubkyExample-PubkyExampleTests/Pods-PubkyExample-PubkyExampleTests.release.xcconfig"; sourceTree = "<group>"; };
|
||||||
|
AF7D486B6E71CFB714642CFB /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; includeInIndex = 1; name = PrivacyInfo.xcprivacy; path = PubkyExample/PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
|
||||||
|
ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; };
|
||||||
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
|
/* Begin PBXFrameworksBuildPhase section */
|
||||||
|
00E356EB1AD99517003FC87E /* Frameworks */ = {
|
||||||
|
isa = PBXFrameworksBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
7699B88040F8A987B510C191 /* libPods-PubkyExample-PubkyExampleTests.a in Frameworks */,
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
13B07F8C1A680F5B00A75B9A /* Frameworks */ = {
|
||||||
|
isa = PBXFrameworksBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
0C80B921A6F3F58F76C31292 /* libPods-PubkyExample.a in Frameworks */,
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
/* End PBXFrameworksBuildPhase section */
|
||||||
|
|
||||||
|
/* Begin PBXGroup section */
|
||||||
|
00E356EF1AD99517003FC87E /* PubkyExampleTests */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
00E356F21AD99517003FC87E /* PubkyExampleTests.m */,
|
||||||
|
00E356F01AD99517003FC87E /* Supporting Files */,
|
||||||
|
);
|
||||||
|
path = PubkyExampleTests;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
00E356F01AD99517003FC87E /* Supporting Files */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
00E356F11AD99517003FC87E /* Info.plist */,
|
||||||
|
);
|
||||||
|
name = "Supporting Files";
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
13B07FAE1A68108700A75B9A /* PubkyExample */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
13B07FAF1A68108700A75B9A /* AppDelegate.h */,
|
||||||
|
13B07FB01A68108700A75B9A /* AppDelegate.mm */,
|
||||||
|
13B07FB51A68108700A75B9A /* Images.xcassets */,
|
||||||
|
13B07FB61A68108700A75B9A /* Info.plist */,
|
||||||
|
81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */,
|
||||||
|
13B07FB71A68108700A75B9A /* main.m */,
|
||||||
|
13B07FB81A68108700A75B9A /* PrivacyInfo.xcprivacy */,
|
||||||
|
AF7D486B6E71CFB714642CFB /* PrivacyInfo.xcprivacy */,
|
||||||
|
);
|
||||||
|
name = PubkyExample;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
2D16E6871FA4F8E400B85C8A /* Frameworks */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
ED297162215061F000B7C4FE /* JavaScriptCore.framework */,
|
||||||
|
5DCACB8F33CDC322A6C60F78 /* libPods-PubkyExample.a */,
|
||||||
|
19F6CBCC0A4E27FBF8BF4A61 /* libPods-PubkyExample-PubkyExampleTests.a */,
|
||||||
|
);
|
||||||
|
name = Frameworks;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
832341AE1AAA6A7D00B99B32 /* Libraries */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
);
|
||||||
|
name = Libraries;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
83CBB9F61A601CBA00E9B192 = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
13B07FAE1A68108700A75B9A /* PubkyExample */,
|
||||||
|
832341AE1AAA6A7D00B99B32 /* Libraries */,
|
||||||
|
00E356EF1AD99517003FC87E /* PubkyExampleTests */,
|
||||||
|
83CBBA001A601CBA00E9B192 /* Products */,
|
||||||
|
2D16E6871FA4F8E400B85C8A /* Frameworks */,
|
||||||
|
BBD78D7AC51CEA395F1C20DB /* Pods */,
|
||||||
|
);
|
||||||
|
indentWidth = 2;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
tabWidth = 2;
|
||||||
|
usesTabs = 0;
|
||||||
|
};
|
||||||
|
83CBBA001A601CBA00E9B192 /* Products */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
13B07F961A680F5B00A75B9A /* PubkyExample.app */,
|
||||||
|
00E356EE1AD99517003FC87E /* PubkyExampleTests.xctest */,
|
||||||
|
);
|
||||||
|
name = Products;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
BBD78D7AC51CEA395F1C20DB /* Pods */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
3B4392A12AC88292D35C810B /* Pods-PubkyExample.debug.xcconfig */,
|
||||||
|
5709B34CF0A7D63546082F79 /* Pods-PubkyExample.release.xcconfig */,
|
||||||
|
5B7EB9410499542E8C5724F5 /* Pods-PubkyExample-PubkyExampleTests.debug.xcconfig */,
|
||||||
|
89C6BE57DB24E9ADA2F236DE /* Pods-PubkyExample-PubkyExampleTests.release.xcconfig */,
|
||||||
|
);
|
||||||
|
path = Pods;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
/* End PBXGroup section */
|
||||||
|
|
||||||
|
/* Begin PBXNativeTarget section */
|
||||||
|
00E356ED1AD99517003FC87E /* PubkyExampleTests */ = {
|
||||||
|
isa = PBXNativeTarget;
|
||||||
|
buildConfigurationList = 00E357021AD99517003FC87E /* Build configuration list for PBXNativeTarget "PubkyExampleTests" */;
|
||||||
|
buildPhases = (
|
||||||
|
A55EABD7B0C7F3A422A6CC61 /* [CP] Check Pods Manifest.lock */,
|
||||||
|
00E356EA1AD99517003FC87E /* Sources */,
|
||||||
|
00E356EB1AD99517003FC87E /* Frameworks */,
|
||||||
|
00E356EC1AD99517003FC87E /* Resources */,
|
||||||
|
C59DA0FBD6956966B86A3779 /* [CP] Embed Pods Frameworks */,
|
||||||
|
F6A41C54EA430FDDC6A6ED99 /* [CP] Copy Pods Resources */,
|
||||||
|
);
|
||||||
|
buildRules = (
|
||||||
|
);
|
||||||
|
dependencies = (
|
||||||
|
00E356F51AD99517003FC87E /* PBXTargetDependency */,
|
||||||
|
);
|
||||||
|
name = PubkyExampleTests;
|
||||||
|
productName = PubkyExampleTests;
|
||||||
|
productReference = 00E356EE1AD99517003FC87E /* PubkyExampleTests.xctest */;
|
||||||
|
productType = "com.apple.product-type.bundle.unit-test";
|
||||||
|
};
|
||||||
|
13B07F861A680F5B00A75B9A /* PubkyExample */ = {
|
||||||
|
isa = PBXNativeTarget;
|
||||||
|
buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "PubkyExample" */;
|
||||||
|
buildPhases = (
|
||||||
|
C38B50BA6285516D6DCD4F65 /* [CP] Check Pods Manifest.lock */,
|
||||||
|
13B07F871A680F5B00A75B9A /* Sources */,
|
||||||
|
13B07F8C1A680F5B00A75B9A /* Frameworks */,
|
||||||
|
13B07F8E1A680F5B00A75B9A /* Resources */,
|
||||||
|
00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */,
|
||||||
|
00EEFC60759A1932668264C0 /* [CP] Embed Pods Frameworks */,
|
||||||
|
E235C05ADACE081382539298 /* [CP] Copy Pods Resources */,
|
||||||
|
);
|
||||||
|
buildRules = (
|
||||||
|
);
|
||||||
|
dependencies = (
|
||||||
|
);
|
||||||
|
name = PubkyExample;
|
||||||
|
productName = PubkyExample;
|
||||||
|
productReference = 13B07F961A680F5B00A75B9A /* PubkyExample.app */;
|
||||||
|
productType = "com.apple.product-type.application";
|
||||||
|
};
|
||||||
|
/* End PBXNativeTarget section */
|
||||||
|
|
||||||
|
/* Begin PBXProject section */
|
||||||
|
83CBB9F71A601CBA00E9B192 /* Project object */ = {
|
||||||
|
isa = PBXProject;
|
||||||
|
attributes = {
|
||||||
|
LastUpgradeCheck = 1210;
|
||||||
|
TargetAttributes = {
|
||||||
|
00E356ED1AD99517003FC87E = {
|
||||||
|
CreatedOnToolsVersion = 6.2;
|
||||||
|
TestTargetID = 13B07F861A680F5B00A75B9A;
|
||||||
|
};
|
||||||
|
13B07F861A680F5B00A75B9A = {
|
||||||
|
LastSwiftMigration = 1120;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
buildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "PubkyExample" */;
|
||||||
|
compatibilityVersion = "Xcode 12.0";
|
||||||
|
developmentRegion = en;
|
||||||
|
hasScannedForEncodings = 0;
|
||||||
|
knownRegions = (
|
||||||
|
en,
|
||||||
|
Base,
|
||||||
|
);
|
||||||
|
mainGroup = 83CBB9F61A601CBA00E9B192;
|
||||||
|
productRefGroup = 83CBBA001A601CBA00E9B192 /* Products */;
|
||||||
|
projectDirPath = "";
|
||||||
|
projectRoot = "";
|
||||||
|
targets = (
|
||||||
|
13B07F861A680F5B00A75B9A /* PubkyExample */,
|
||||||
|
00E356ED1AD99517003FC87E /* PubkyExampleTests */,
|
||||||
|
);
|
||||||
|
};
|
||||||
|
/* End PBXProject section */
|
||||||
|
|
||||||
|
/* Begin PBXResourcesBuildPhase section */
|
||||||
|
00E356EC1AD99517003FC87E /* Resources */ = {
|
||||||
|
isa = PBXResourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
13B07F8E1A680F5B00A75B9A /* Resources */ = {
|
||||||
|
isa = PBXResourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */,
|
||||||
|
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */,
|
||||||
|
B2A00F0E44E958DA013ABFD6 /* PrivacyInfo.xcprivacy in Resources */,
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
/* End PBXResourcesBuildPhase section */
|
||||||
|
|
||||||
|
/* Begin PBXShellScriptBuildPhase section */
|
||||||
|
00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */ = {
|
||||||
|
isa = PBXShellScriptBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
inputPaths = (
|
||||||
|
"$(SRCROOT)/.xcode.env.local",
|
||||||
|
"$(SRCROOT)/.xcode.env",
|
||||||
|
);
|
||||||
|
name = "Bundle React Native code and images";
|
||||||
|
outputPaths = (
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
shellPath = /bin/sh;
|
||||||
|
shellScript = "set -e\n\nWITH_ENVIRONMENT=\"$REACT_NATIVE_PATH/scripts/xcode/with-environment.sh\"\nREACT_NATIVE_XCODE=\"$REACT_NATIVE_PATH/scripts/react-native-xcode.sh\"\n\n/bin/sh -c \"$WITH_ENVIRONMENT $REACT_NATIVE_XCODE\"\n";
|
||||||
|
};
|
||||||
|
00EEFC60759A1932668264C0 /* [CP] Embed Pods Frameworks */ = {
|
||||||
|
isa = PBXShellScriptBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
inputFileListPaths = (
|
||||||
|
"${PODS_ROOT}/Target Support Files/Pods-PubkyExample/Pods-PubkyExample-frameworks-${CONFIGURATION}-input-files.xcfilelist",
|
||||||
|
);
|
||||||
|
name = "[CP] Embed Pods Frameworks";
|
||||||
|
outputFileListPaths = (
|
||||||
|
"${PODS_ROOT}/Target Support Files/Pods-PubkyExample/Pods-PubkyExample-frameworks-${CONFIGURATION}-output-files.xcfilelist",
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
shellPath = /bin/sh;
|
||||||
|
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-PubkyExample/Pods-PubkyExample-frameworks.sh\"\n";
|
||||||
|
showEnvVarsInLog = 0;
|
||||||
|
};
|
||||||
|
A55EABD7B0C7F3A422A6CC61 /* [CP] Check Pods Manifest.lock */ = {
|
||||||
|
isa = PBXShellScriptBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
inputFileListPaths = (
|
||||||
|
);
|
||||||
|
inputPaths = (
|
||||||
|
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
|
||||||
|
"${PODS_ROOT}/Manifest.lock",
|
||||||
|
);
|
||||||
|
name = "[CP] Check Pods Manifest.lock";
|
||||||
|
outputFileListPaths = (
|
||||||
|
);
|
||||||
|
outputPaths = (
|
||||||
|
"$(DERIVED_FILE_DIR)/Pods-PubkyExample-PubkyExampleTests-checkManifestLockResult.txt",
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
shellPath = /bin/sh;
|
||||||
|
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
||||||
|
showEnvVarsInLog = 0;
|
||||||
|
};
|
||||||
|
C38B50BA6285516D6DCD4F65 /* [CP] Check Pods Manifest.lock */ = {
|
||||||
|
isa = PBXShellScriptBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
inputFileListPaths = (
|
||||||
|
);
|
||||||
|
inputPaths = (
|
||||||
|
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
|
||||||
|
"${PODS_ROOT}/Manifest.lock",
|
||||||
|
);
|
||||||
|
name = "[CP] Check Pods Manifest.lock";
|
||||||
|
outputFileListPaths = (
|
||||||
|
);
|
||||||
|
outputPaths = (
|
||||||
|
"$(DERIVED_FILE_DIR)/Pods-PubkyExample-checkManifestLockResult.txt",
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
shellPath = /bin/sh;
|
||||||
|
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
||||||
|
showEnvVarsInLog = 0;
|
||||||
|
};
|
||||||
|
C59DA0FBD6956966B86A3779 /* [CP] Embed Pods Frameworks */ = {
|
||||||
|
isa = PBXShellScriptBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
inputFileListPaths = (
|
||||||
|
"${PODS_ROOT}/Target Support Files/Pods-PubkyExample-PubkyExampleTests/Pods-PubkyExample-PubkyExampleTests-frameworks-${CONFIGURATION}-input-files.xcfilelist",
|
||||||
|
);
|
||||||
|
name = "[CP] Embed Pods Frameworks";
|
||||||
|
outputFileListPaths = (
|
||||||
|
"${PODS_ROOT}/Target Support Files/Pods-PubkyExample-PubkyExampleTests/Pods-PubkyExample-PubkyExampleTests-frameworks-${CONFIGURATION}-output-files.xcfilelist",
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
shellPath = /bin/sh;
|
||||||
|
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-PubkyExample-PubkyExampleTests/Pods-PubkyExample-PubkyExampleTests-frameworks.sh\"\n";
|
||||||
|
showEnvVarsInLog = 0;
|
||||||
|
};
|
||||||
|
E235C05ADACE081382539298 /* [CP] Copy Pods Resources */ = {
|
||||||
|
isa = PBXShellScriptBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
inputFileListPaths = (
|
||||||
|
"${PODS_ROOT}/Target Support Files/Pods-PubkyExample/Pods-PubkyExample-resources-${CONFIGURATION}-input-files.xcfilelist",
|
||||||
|
);
|
||||||
|
name = "[CP] Copy Pods Resources";
|
||||||
|
outputFileListPaths = (
|
||||||
|
"${PODS_ROOT}/Target Support Files/Pods-PubkyExample/Pods-PubkyExample-resources-${CONFIGURATION}-output-files.xcfilelist",
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
shellPath = /bin/sh;
|
||||||
|
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-PubkyExample/Pods-PubkyExample-resources.sh\"\n";
|
||||||
|
showEnvVarsInLog = 0;
|
||||||
|
};
|
||||||
|
F6A41C54EA430FDDC6A6ED99 /* [CP] Copy Pods Resources */ = {
|
||||||
|
isa = PBXShellScriptBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
inputFileListPaths = (
|
||||||
|
"${PODS_ROOT}/Target Support Files/Pods-PubkyExample-PubkyExampleTests/Pods-PubkyExample-PubkyExampleTests-resources-${CONFIGURATION}-input-files.xcfilelist",
|
||||||
|
);
|
||||||
|
name = "[CP] Copy Pods Resources";
|
||||||
|
outputFileListPaths = (
|
||||||
|
"${PODS_ROOT}/Target Support Files/Pods-PubkyExample-PubkyExampleTests/Pods-PubkyExample-PubkyExampleTests-resources-${CONFIGURATION}-output-files.xcfilelist",
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
shellPath = /bin/sh;
|
||||||
|
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-PubkyExample-PubkyExampleTests/Pods-PubkyExample-PubkyExampleTests-resources.sh\"\n";
|
||||||
|
showEnvVarsInLog = 0;
|
||||||
|
};
|
||||||
|
/* End PBXShellScriptBuildPhase section */
|
||||||
|
|
||||||
|
/* Begin PBXSourcesBuildPhase section */
|
||||||
|
00E356EA1AD99517003FC87E /* Sources */ = {
|
||||||
|
isa = PBXSourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
00E356F31AD99517003FC87E /* PubkyExampleTests.m in Sources */,
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
13B07F871A680F5B00A75B9A /* Sources */ = {
|
||||||
|
isa = PBXSourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
13B07FBC1A68108700A75B9A /* AppDelegate.mm in Sources */,
|
||||||
|
13B07FC11A68108700A75B9A /* main.m in Sources */,
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
/* End PBXSourcesBuildPhase section */
|
||||||
|
|
||||||
|
/* Begin PBXTargetDependency section */
|
||||||
|
00E356F51AD99517003FC87E /* PBXTargetDependency */ = {
|
||||||
|
isa = PBXTargetDependency;
|
||||||
|
target = 13B07F861A680F5B00A75B9A /* PubkyExample */;
|
||||||
|
targetProxy = 00E356F41AD99517003FC87E /* PBXContainerItemProxy */;
|
||||||
|
};
|
||||||
|
/* End PBXTargetDependency section */
|
||||||
|
|
||||||
|
/* Begin XCBuildConfiguration section */
|
||||||
|
00E356F61AD99517003FC87E /* Debug */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
baseConfigurationReference = 5B7EB9410499542E8C5724F5 /* Pods-PubkyExample-PubkyExampleTests.debug.xcconfig */;
|
||||||
|
buildSettings = {
|
||||||
|
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||||
|
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||||
|
"DEBUG=1",
|
||||||
|
"$(inherited)",
|
||||||
|
);
|
||||||
|
INFOPLIST_FILE = PubkyExampleTests/Info.plist;
|
||||||
|
IPHONEOS_DEPLOYMENT_TARGET = 13.4;
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
"$(inherited)",
|
||||||
|
"@executable_path/Frameworks",
|
||||||
|
"@loader_path/Frameworks",
|
||||||
|
);
|
||||||
|
OTHER_LDFLAGS = (
|
||||||
|
"-ObjC",
|
||||||
|
"-lc++",
|
||||||
|
"$(inherited)",
|
||||||
|
);
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = pubky.example;
|
||||||
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/PubkyExample.app/PubkyExample";
|
||||||
|
};
|
||||||
|
name = Debug;
|
||||||
|
};
|
||||||
|
00E356F71AD99517003FC87E /* Release */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
baseConfigurationReference = 89C6BE57DB24E9ADA2F236DE /* Pods-PubkyExample-PubkyExampleTests.release.xcconfig */;
|
||||||
|
buildSettings = {
|
||||||
|
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||||
|
COPY_PHASE_STRIP = NO;
|
||||||
|
INFOPLIST_FILE = PubkyExampleTests/Info.plist;
|
||||||
|
IPHONEOS_DEPLOYMENT_TARGET = 13.4;
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
"$(inherited)",
|
||||||
|
"@executable_path/Frameworks",
|
||||||
|
"@loader_path/Frameworks",
|
||||||
|
);
|
||||||
|
OTHER_LDFLAGS = (
|
||||||
|
"-ObjC",
|
||||||
|
"-lc++",
|
||||||
|
"$(inherited)",
|
||||||
|
);
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = pubky.example;
|
||||||
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/PubkyExample.app/PubkyExample";
|
||||||
|
};
|
||||||
|
name = Release;
|
||||||
|
};
|
||||||
|
13B07F941A680F5B00A75B9A /* Debug */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
baseConfigurationReference = 3B4392A12AC88292D35C810B /* Pods-PubkyExample.debug.xcconfig */;
|
||||||
|
buildSettings = {
|
||||||
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
|
CLANG_ENABLE_MODULES = YES;
|
||||||
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
|
ENABLE_BITCODE = NO;
|
||||||
|
INFOPLIST_FILE = PubkyExample/Info.plist;
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
"$(inherited)",
|
||||||
|
"@executable_path/Frameworks",
|
||||||
|
);
|
||||||
|
MARKETING_VERSION = 1.0;
|
||||||
|
OTHER_LDFLAGS = (
|
||||||
|
"$(inherited)",
|
||||||
|
"-ObjC",
|
||||||
|
"-lc++",
|
||||||
|
);
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = pubky.example;
|
||||||
|
PRODUCT_NAME = PubkyExample;
|
||||||
|
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||||
|
SWIFT_VERSION = 5.0;
|
||||||
|
VERSIONING_SYSTEM = "apple-generic";
|
||||||
|
};
|
||||||
|
name = Debug;
|
||||||
|
};
|
||||||
|
13B07F951A680F5B00A75B9A /* Release */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
baseConfigurationReference = 5709B34CF0A7D63546082F79 /* Pods-PubkyExample.release.xcconfig */;
|
||||||
|
buildSettings = {
|
||||||
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
|
CLANG_ENABLE_MODULES = YES;
|
||||||
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
|
INFOPLIST_FILE = PubkyExample/Info.plist;
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
"$(inherited)",
|
||||||
|
"@executable_path/Frameworks",
|
||||||
|
);
|
||||||
|
MARKETING_VERSION = 1.0;
|
||||||
|
OTHER_LDFLAGS = (
|
||||||
|
"$(inherited)",
|
||||||
|
"-ObjC",
|
||||||
|
"-lc++",
|
||||||
|
);
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = pubky.example;
|
||||||
|
PRODUCT_NAME = PubkyExample;
|
||||||
|
SWIFT_VERSION = 5.0;
|
||||||
|
VERSIONING_SYSTEM = "apple-generic";
|
||||||
|
};
|
||||||
|
name = Release;
|
||||||
|
};
|
||||||
|
83CBBA201A601CBA00E9B192 /* Debug */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||||
|
CC = "";
|
||||||
|
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
|
||||||
|
CLANG_CXX_LANGUAGE_STANDARD = "c++20";
|
||||||
|
CLANG_CXX_LIBRARY = "libc++";
|
||||||
|
CLANG_ENABLE_MODULES = YES;
|
||||||
|
CLANG_ENABLE_OBJC_ARC = YES;
|
||||||
|
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||||
|
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_COMMA = YES;
|
||||||
|
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||||
|
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||||
|
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||||
|
CLANG_WARN_EMPTY_BODY = YES;
|
||||||
|
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||||
|
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||||
|
CLANG_WARN_INT_CONVERSION = YES;
|
||||||
|
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||||
|
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||||
|
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
||||||
|
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||||
|
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||||
|
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||||
|
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||||
|
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||||
|
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||||
|
COPY_PHASE_STRIP = NO;
|
||||||
|
CXX = "";
|
||||||
|
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||||
|
ENABLE_TESTABILITY = YES;
|
||||||
|
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "";
|
||||||
|
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||||
|
GCC_DYNAMIC_NO_PIC = NO;
|
||||||
|
GCC_NO_COMMON_BLOCKS = YES;
|
||||||
|
GCC_OPTIMIZATION_LEVEL = 0;
|
||||||
|
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||||
|
"DEBUG=1",
|
||||||
|
"$(inherited)",
|
||||||
|
);
|
||||||
|
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
|
||||||
|
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||||
|
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||||
|
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||||
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||||
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
|
IPHONEOS_DEPLOYMENT_TARGET = 13.4;
|
||||||
|
LD = "";
|
||||||
|
LDPLUSPLUS = "";
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
/usr/lib/swift,
|
||||||
|
"$(inherited)",
|
||||||
|
);
|
||||||
|
LIBRARY_SEARCH_PATHS = (
|
||||||
|
"\"$(SDKROOT)/usr/lib/swift\"",
|
||||||
|
"\"$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)\"",
|
||||||
|
"\"$(inherited)\"",
|
||||||
|
);
|
||||||
|
MTL_ENABLE_DEBUG_INFO = YES;
|
||||||
|
ONLY_ACTIVE_ARCH = YES;
|
||||||
|
OTHER_CPLUSPLUSFLAGS = (
|
||||||
|
"$(OTHER_CFLAGS)",
|
||||||
|
"-DFOLLY_NO_CONFIG",
|
||||||
|
"-DFOLLY_MOBILE=1",
|
||||||
|
"-DFOLLY_USE_LIBCPP=1",
|
||||||
|
"-DFOLLY_CFG_NO_COROUTINES=1",
|
||||||
|
"-DFOLLY_HAVE_CLOCK_GETTIME=1",
|
||||||
|
);
|
||||||
|
OTHER_LDFLAGS = (
|
||||||
|
"$(inherited)",
|
||||||
|
" ",
|
||||||
|
);
|
||||||
|
REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
|
||||||
|
SDKROOT = iphoneos;
|
||||||
|
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) DEBUG";
|
||||||
|
USE_HERMES = true;
|
||||||
|
};
|
||||||
|
name = Debug;
|
||||||
|
};
|
||||||
|
83CBBA211A601CBA00E9B192 /* Release */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||||
|
CC = "";
|
||||||
|
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
|
||||||
|
CLANG_CXX_LANGUAGE_STANDARD = "c++20";
|
||||||
|
CLANG_CXX_LIBRARY = "libc++";
|
||||||
|
CLANG_ENABLE_MODULES = YES;
|
||||||
|
CLANG_ENABLE_OBJC_ARC = YES;
|
||||||
|
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||||
|
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_COMMA = YES;
|
||||||
|
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||||
|
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||||
|
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||||
|
CLANG_WARN_EMPTY_BODY = YES;
|
||||||
|
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||||
|
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||||
|
CLANG_WARN_INT_CONVERSION = YES;
|
||||||
|
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||||
|
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||||
|
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
||||||
|
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||||
|
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||||
|
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||||
|
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||||
|
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||||
|
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||||
|
COPY_PHASE_STRIP = YES;
|
||||||
|
CXX = "";
|
||||||
|
ENABLE_NS_ASSERTIONS = NO;
|
||||||
|
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||||
|
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "";
|
||||||
|
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||||
|
GCC_NO_COMMON_BLOCKS = YES;
|
||||||
|
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||||
|
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||||
|
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||||
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||||
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
|
IPHONEOS_DEPLOYMENT_TARGET = 13.4;
|
||||||
|
LD = "";
|
||||||
|
LDPLUSPLUS = "";
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
/usr/lib/swift,
|
||||||
|
"$(inherited)",
|
||||||
|
);
|
||||||
|
LIBRARY_SEARCH_PATHS = (
|
||||||
|
"\"$(SDKROOT)/usr/lib/swift\"",
|
||||||
|
"\"$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)\"",
|
||||||
|
"\"$(inherited)\"",
|
||||||
|
);
|
||||||
|
MTL_ENABLE_DEBUG_INFO = NO;
|
||||||
|
OTHER_CPLUSPLUSFLAGS = (
|
||||||
|
"$(OTHER_CFLAGS)",
|
||||||
|
"-DFOLLY_NO_CONFIG",
|
||||||
|
"-DFOLLY_MOBILE=1",
|
||||||
|
"-DFOLLY_USE_LIBCPP=1",
|
||||||
|
"-DFOLLY_CFG_NO_COROUTINES=1",
|
||||||
|
"-DFOLLY_HAVE_CLOCK_GETTIME=1",
|
||||||
|
);
|
||||||
|
OTHER_LDFLAGS = (
|
||||||
|
"$(inherited)",
|
||||||
|
" ",
|
||||||
|
);
|
||||||
|
REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
|
||||||
|
SDKROOT = iphoneos;
|
||||||
|
USE_HERMES = true;
|
||||||
|
VALIDATE_PRODUCT = YES;
|
||||||
|
};
|
||||||
|
name = Release;
|
||||||
|
};
|
||||||
|
/* End XCBuildConfiguration section */
|
||||||
|
|
||||||
|
/* Begin XCConfigurationList section */
|
||||||
|
00E357021AD99517003FC87E /* Build configuration list for PBXNativeTarget "PubkyExampleTests" */ = {
|
||||||
|
isa = XCConfigurationList;
|
||||||
|
buildConfigurations = (
|
||||||
|
00E356F61AD99517003FC87E /* Debug */,
|
||||||
|
00E356F71AD99517003FC87E /* Release */,
|
||||||
|
);
|
||||||
|
defaultConfigurationIsVisible = 0;
|
||||||
|
defaultConfigurationName = Release;
|
||||||
|
};
|
||||||
|
13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "PubkyExample" */ = {
|
||||||
|
isa = XCConfigurationList;
|
||||||
|
buildConfigurations = (
|
||||||
|
13B07F941A680F5B00A75B9A /* Debug */,
|
||||||
|
13B07F951A680F5B00A75B9A /* Release */,
|
||||||
|
);
|
||||||
|
defaultConfigurationIsVisible = 0;
|
||||||
|
defaultConfigurationName = Release;
|
||||||
|
};
|
||||||
|
83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "PubkyExample" */ = {
|
||||||
|
isa = XCConfigurationList;
|
||||||
|
buildConfigurations = (
|
||||||
|
83CBBA201A601CBA00E9B192 /* Debug */,
|
||||||
|
83CBBA211A601CBA00E9B192 /* Release */,
|
||||||
|
);
|
||||||
|
defaultConfigurationIsVisible = 0;
|
||||||
|
defaultConfigurationName = Release;
|
||||||
|
};
|
||||||
|
/* End XCConfigurationList section */
|
||||||
|
};
|
||||||
|
rootObject = 83CBB9F71A601CBA00E9B192 /* Project object */;
|
||||||
|
}
|
||||||
@@ -0,0 +1,88 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Scheme
|
||||||
|
LastUpgradeVersion = "1210"
|
||||||
|
version = "1.3">
|
||||||
|
<BuildAction
|
||||||
|
parallelizeBuildables = "YES"
|
||||||
|
buildImplicitDependencies = "YES">
|
||||||
|
<BuildActionEntries>
|
||||||
|
<BuildActionEntry
|
||||||
|
buildForTesting = "YES"
|
||||||
|
buildForRunning = "YES"
|
||||||
|
buildForProfiling = "YES"
|
||||||
|
buildForArchiving = "YES"
|
||||||
|
buildForAnalyzing = "YES">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
|
||||||
|
BuildableName = "PubkyExample.app"
|
||||||
|
BlueprintName = "PubkyExample"
|
||||||
|
ReferencedContainer = "container:PubkyExample.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildActionEntry>
|
||||||
|
</BuildActionEntries>
|
||||||
|
</BuildAction>
|
||||||
|
<TestAction
|
||||||
|
buildConfiguration = "Debug"
|
||||||
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||||
|
<Testables>
|
||||||
|
<TestableReference
|
||||||
|
skipped = "NO">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "00E356ED1AD99517003FC87E"
|
||||||
|
BuildableName = "PubkyExampleTests.xctest"
|
||||||
|
BlueprintName = "PubkyExampleTests"
|
||||||
|
ReferencedContainer = "container:PubkyExample.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</TestableReference>
|
||||||
|
</Testables>
|
||||||
|
</TestAction>
|
||||||
|
<LaunchAction
|
||||||
|
buildConfiguration = "Debug"
|
||||||
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
launchStyle = "0"
|
||||||
|
useCustomWorkingDirectory = "NO"
|
||||||
|
ignoresPersistentStateOnLaunch = "NO"
|
||||||
|
debugDocumentVersioning = "YES"
|
||||||
|
debugServiceExtension = "internal"
|
||||||
|
allowLocationSimulation = "YES">
|
||||||
|
<BuildableProductRunnable
|
||||||
|
runnableDebuggingMode = "0">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
|
||||||
|
BuildableName = "PubkyExample.app"
|
||||||
|
BlueprintName = "PubkyExample"
|
||||||
|
ReferencedContainer = "container:PubkyExample.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildableProductRunnable>
|
||||||
|
</LaunchAction>
|
||||||
|
<ProfileAction
|
||||||
|
buildConfiguration = "Release"
|
||||||
|
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||||
|
savedToolIdentifier = ""
|
||||||
|
useCustomWorkingDirectory = "NO"
|
||||||
|
debugDocumentVersioning = "YES">
|
||||||
|
<BuildableProductRunnable
|
||||||
|
runnableDebuggingMode = "0">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
|
||||||
|
BuildableName = "PubkyExample.app"
|
||||||
|
BlueprintName = "PubkyExample"
|
||||||
|
ReferencedContainer = "container:PubkyExample.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildableProductRunnable>
|
||||||
|
</ProfileAction>
|
||||||
|
<AnalyzeAction
|
||||||
|
buildConfiguration = "Debug">
|
||||||
|
</AnalyzeAction>
|
||||||
|
<ArchiveAction
|
||||||
|
buildConfiguration = "Release"
|
||||||
|
revealArchiveInOrganizer = "YES">
|
||||||
|
</ArchiveAction>
|
||||||
|
</Scheme>
|
||||||
10
example/ios/PubkyExample.xcworkspace/contents.xcworkspacedata
generated
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Workspace
|
||||||
|
version = "1.0">
|
||||||
|
<FileRef
|
||||||
|
location = "group:PubkyExample.xcodeproj">
|
||||||
|
</FileRef>
|
||||||
|
<FileRef
|
||||||
|
location = "group:Pods/Pods.xcodeproj">
|
||||||
|
</FileRef>
|
||||||
|
</Workspace>
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>IDEDidComputeMac32BitWarning</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
6
example/ios/PubkyExample/AppDelegate.h
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
#import <RCTAppDelegate.h>
|
||||||
|
#import <UIKit/UIKit.h>
|
||||||
|
|
||||||
|
@interface AppDelegate : RCTAppDelegate
|
||||||
|
|
||||||
|
@end
|
||||||
31
example/ios/PubkyExample/AppDelegate.mm
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
#import "AppDelegate.h"
|
||||||
|
|
||||||
|
#import <React/RCTBundleURLProvider.h>
|
||||||
|
|
||||||
|
@implementation AppDelegate
|
||||||
|
|
||||||
|
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
|
||||||
|
{
|
||||||
|
self.moduleName = @"PubkyExample";
|
||||||
|
// You can add your custom initial props in the dictionary below.
|
||||||
|
// They will be passed down to the ViewController used by React Native.
|
||||||
|
self.initialProps = @{};
|
||||||
|
|
||||||
|
return [super application:application didFinishLaunchingWithOptions:launchOptions];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
|
||||||
|
{
|
||||||
|
return [self bundleURL];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSURL *)bundleURL
|
||||||
|
{
|
||||||
|
#if DEBUG
|
||||||
|
return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index"];
|
||||||
|
#else
|
||||||
|
return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"idiom" : "iphone",
|
||||||
|
"scale" : "2x",
|
||||||
|
"size" : "20x20"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "iphone",
|
||||||
|
"scale" : "3x",
|
||||||
|
"size" : "20x20"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "iphone",
|
||||||
|
"scale" : "2x",
|
||||||
|
"size" : "29x29"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "iphone",
|
||||||
|
"scale" : "3x",
|
||||||
|
"size" : "29x29"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "iphone",
|
||||||
|
"scale" : "2x",
|
||||||
|
"size" : "40x40"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "iphone",
|
||||||
|
"scale" : "3x",
|
||||||
|
"size" : "40x40"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "iphone",
|
||||||
|
"scale" : "2x",
|
||||||
|
"size" : "60x60"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "iphone",
|
||||||
|
"scale" : "3x",
|
||||||
|
"size" : "60x60"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "ios-marketing",
|
||||||
|
"scale" : "1x",
|
||||||
|
"size" : "1024x1024"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
6
example/ios/PubkyExample/Images.xcassets/Contents.json
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"info" : {
|
||||||
|
"version" : 1,
|
||||||
|
"author" : "xcode"
|
||||||
|
}
|
||||||
|
}
|
||||||
52
example/ios/PubkyExample/Info.plist
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
|
<string>en</string>
|
||||||
|
<key>CFBundleDisplayName</key>
|
||||||
|
<string>PubkyExample</string>
|
||||||
|
<key>CFBundleExecutable</key>
|
||||||
|
<string>$(EXECUTABLE_NAME)</string>
|
||||||
|
<key>CFBundleIdentifier</key>
|
||||||
|
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||||
|
<key>CFBundleInfoDictionaryVersion</key>
|
||||||
|
<string>6.0</string>
|
||||||
|
<key>CFBundleName</key>
|
||||||
|
<string>$(PRODUCT_NAME)</string>
|
||||||
|
<key>CFBundlePackageType</key>
|
||||||
|
<string>APPL</string>
|
||||||
|
<key>CFBundleShortVersionString</key>
|
||||||
|
<string>$(MARKETING_VERSION)</string>
|
||||||
|
<key>CFBundleSignature</key>
|
||||||
|
<string>????</string>
|
||||||
|
<key>CFBundleVersion</key>
|
||||||
|
<string>$(CURRENT_PROJECT_VERSION)</string>
|
||||||
|
<key>LSRequiresIPhoneOS</key>
|
||||||
|
<true/>
|
||||||
|
<key>NSAppTransportSecurity</key>
|
||||||
|
<dict>
|
||||||
|
<!-- Do not change NSAllowsArbitraryLoads to true, or you will risk app rejection! -->
|
||||||
|
<key>NSAllowsArbitraryLoads</key>
|
||||||
|
<false/>
|
||||||
|
<key>NSAllowsLocalNetworking</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
|
<key>NSLocationWhenInUseUsageDescription</key>
|
||||||
|
<string></string>
|
||||||
|
<key>UILaunchStoryboardName</key>
|
||||||
|
<string>LaunchScreen</string>
|
||||||
|
<key>UIRequiredDeviceCapabilities</key>
|
||||||
|
<array>
|
||||||
|
<string>arm64</string>
|
||||||
|
</array>
|
||||||
|
<key>UISupportedInterfaceOrientations</key>
|
||||||
|
<array>
|
||||||
|
<string>UIInterfaceOrientationPortrait</string>
|
||||||
|
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||||
|
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||||
|
</array>
|
||||||
|
<key>UIViewControllerBasedStatusBarAppearance</key>
|
||||||
|
<false/>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
47
example/ios/PubkyExample/LaunchScreen.storyboard
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="15702" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
|
||||||
|
<device id="retina4_7" orientation="portrait" appearance="light"/>
|
||||||
|
<dependencies>
|
||||||
|
<deployment identifier="iOS"/>
|
||||||
|
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="15704"/>
|
||||||
|
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
|
||||||
|
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||||
|
</dependencies>
|
||||||
|
<scenes>
|
||||||
|
<!--View Controller-->
|
||||||
|
<scene sceneID="EHf-IW-A2E">
|
||||||
|
<objects>
|
||||||
|
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
|
||||||
|
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
|
||||||
|
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
|
<subviews>
|
||||||
|
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="PubkyExample" textAlignment="center" lineBreakMode="middleTruncation" baselineAdjustment="alignBaselines" minimumFontSize="18" translatesAutoresizingMaskIntoConstraints="NO" id="GJd-Yh-RWb">
|
||||||
|
<rect key="frame" x="0.0" y="202" width="375" height="43"/>
|
||||||
|
<fontDescription key="fontDescription" type="boldSystem" pointSize="36"/>
|
||||||
|
<nil key="highlightedColor"/>
|
||||||
|
</label>
|
||||||
|
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Powered by React Native" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="9" translatesAutoresizingMaskIntoConstraints="NO" id="MN2-I3-ftu">
|
||||||
|
<rect key="frame" x="0.0" y="626" width="375" height="21"/>
|
||||||
|
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||||
|
<nil key="highlightedColor"/>
|
||||||
|
</label>
|
||||||
|
</subviews>
|
||||||
|
<color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
|
||||||
|
<constraints>
|
||||||
|
<constraint firstItem="Bcu-3y-fUS" firstAttribute="bottom" secondItem="MN2-I3-ftu" secondAttribute="bottom" constant="20" id="OZV-Vh-mqD"/>
|
||||||
|
<constraint firstItem="Bcu-3y-fUS" firstAttribute="centerX" secondItem="GJd-Yh-RWb" secondAttribute="centerX" id="Q3B-4B-g5h"/>
|
||||||
|
<constraint firstItem="MN2-I3-ftu" firstAttribute="centerX" secondItem="Bcu-3y-fUS" secondAttribute="centerX" id="akx-eg-2ui"/>
|
||||||
|
<constraint firstItem="MN2-I3-ftu" firstAttribute="leading" secondItem="Bcu-3y-fUS" secondAttribute="leading" id="i1E-0Y-4RG"/>
|
||||||
|
<constraint firstItem="GJd-Yh-RWb" firstAttribute="centerY" secondItem="Ze5-6b-2t3" secondAttribute="bottom" multiplier="1/3" constant="1" id="moa-c2-u7t"/>
|
||||||
|
<constraint firstItem="GJd-Yh-RWb" firstAttribute="leading" secondItem="Bcu-3y-fUS" secondAttribute="leading" symbolic="YES" id="x7j-FC-K8j"/>
|
||||||
|
</constraints>
|
||||||
|
<viewLayoutGuide key="safeArea" id="Bcu-3y-fUS"/>
|
||||||
|
</view>
|
||||||
|
</viewController>
|
||||||
|
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||||
|
</objects>
|
||||||
|
<point key="canvasLocation" x="52.173913043478265" y="375"/>
|
||||||
|
</scene>
|
||||||
|
</scenes>
|
||||||
|
</document>
|
||||||
37
example/ios/PubkyExample/PrivacyInfo.xcprivacy
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>NSPrivacyAccessedAPITypes</key>
|
||||||
|
<array>
|
||||||
|
<dict>
|
||||||
|
<key>NSPrivacyAccessedAPIType</key>
|
||||||
|
<string>NSPrivacyAccessedAPICategoryFileTimestamp</string>
|
||||||
|
<key>NSPrivacyAccessedAPITypeReasons</key>
|
||||||
|
<array>
|
||||||
|
<string>C617.1</string>
|
||||||
|
</array>
|
||||||
|
</dict>
|
||||||
|
<dict>
|
||||||
|
<key>NSPrivacyAccessedAPIType</key>
|
||||||
|
<string>NSPrivacyAccessedAPICategoryUserDefaults</string>
|
||||||
|
<key>NSPrivacyAccessedAPITypeReasons</key>
|
||||||
|
<array>
|
||||||
|
<string>CA92.1</string>
|
||||||
|
</array>
|
||||||
|
</dict>
|
||||||
|
<dict>
|
||||||
|
<key>NSPrivacyAccessedAPIType</key>
|
||||||
|
<string>NSPrivacyAccessedAPICategorySystemBootTime</string>
|
||||||
|
<key>NSPrivacyAccessedAPITypeReasons</key>
|
||||||
|
<array>
|
||||||
|
<string>35F9.1</string>
|
||||||
|
</array>
|
||||||
|
</dict>
|
||||||
|
</array>
|
||||||
|
<key>NSPrivacyCollectedDataTypes</key>
|
||||||
|
<array/>
|
||||||
|
<key>NSPrivacyTracking</key>
|
||||||
|
<false/>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
10
example/ios/PubkyExample/main.m
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
#import <UIKit/UIKit.h>
|
||||||
|
|
||||||
|
#import "AppDelegate.h"
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
@autoreleasepool {
|
||||||
|
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
|
||||||
|
}
|
||||||
|
}
|
||||||
24
example/ios/PubkyExampleTests/Info.plist
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
|
<string>en</string>
|
||||||
|
<key>CFBundleExecutable</key>
|
||||||
|
<string>$(EXECUTABLE_NAME)</string>
|
||||||
|
<key>CFBundleIdentifier</key>
|
||||||
|
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||||
|
<key>CFBundleInfoDictionaryVersion</key>
|
||||||
|
<string>6.0</string>
|
||||||
|
<key>CFBundleName</key>
|
||||||
|
<string>$(PRODUCT_NAME)</string>
|
||||||
|
<key>CFBundlePackageType</key>
|
||||||
|
<string>BNDL</string>
|
||||||
|
<key>CFBundleShortVersionString</key>
|
||||||
|
<string>1.0</string>
|
||||||
|
<key>CFBundleSignature</key>
|
||||||
|
<string>????</string>
|
||||||
|
<key>CFBundleVersion</key>
|
||||||
|
<string>1</string>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
66
example/ios/PubkyExampleTests/PubkyExampleTests.m
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
#import <UIKit/UIKit.h>
|
||||||
|
#import <XCTest/XCTest.h>
|
||||||
|
|
||||||
|
#import <React/RCTLog.h>
|
||||||
|
#import <React/RCTRootView.h>
|
||||||
|
|
||||||
|
#define TIMEOUT_SECONDS 600
|
||||||
|
#define TEXT_TO_LOOK_FOR @"Welcome to React"
|
||||||
|
|
||||||
|
@interface PubkyExampleTests : XCTestCase
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation PubkyExampleTests
|
||||||
|
|
||||||
|
- (BOOL)findSubviewInView:(UIView *)view matching:(BOOL (^)(UIView *view))test
|
||||||
|
{
|
||||||
|
if (test(view)) {
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
for (UIView *subview in [view subviews]) {
|
||||||
|
if ([self findSubviewInView:subview matching:test]) {
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)testRendersWelcomeScreen
|
||||||
|
{
|
||||||
|
UIViewController *vc = [[[RCTSharedApplication() delegate] window] rootViewController];
|
||||||
|
NSDate *date = [NSDate dateWithTimeIntervalSinceNow:TIMEOUT_SECONDS];
|
||||||
|
BOOL foundElement = NO;
|
||||||
|
|
||||||
|
__block NSString *redboxError = nil;
|
||||||
|
#ifdef DEBUG
|
||||||
|
RCTSetLogFunction(
|
||||||
|
^(RCTLogLevel level, RCTLogSource source, NSString *fileName, NSNumber *lineNumber, NSString *message) {
|
||||||
|
if (level >= RCTLogLevelError) {
|
||||||
|
redboxError = message;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
#endif
|
||||||
|
|
||||||
|
while ([date timeIntervalSinceNow] > 0 && !foundElement && !redboxError) {
|
||||||
|
[[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
|
||||||
|
[[NSRunLoop mainRunLoop] runMode:NSRunLoopCommonModes beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
|
||||||
|
|
||||||
|
foundElement = [self findSubviewInView:vc.view
|
||||||
|
matching:^BOOL(UIView *view) {
|
||||||
|
if ([view.accessibilityLabel isEqualToString:TEXT_TO_LOOK_FOR]) {
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
return NO;
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
RCTSetLogFunction(RCTDefaultLogFunction);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
XCTAssertNil(redboxError, @"RedBox error: %@", redboxError);
|
||||||
|
XCTAssertTrue(foundElement, @"Couldn't find element with text '%@' in %d seconds", TEXT_TO_LOOK_FOR, TIMEOUT_SECONDS);
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
3
example/jest.config.js
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
module.exports = {
|
||||||
|
preset: 'react-native',
|
||||||
|
};
|
||||||
18
example/metro.config.js
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
const path = require('path');
|
||||||
|
const { getDefaultConfig } = require('@react-native/metro-config');
|
||||||
|
const { getConfig } = require('react-native-builder-bob/metro-config');
|
||||||
|
const pkg = require('../package.json');
|
||||||
|
|
||||||
|
const root = path.resolve(__dirname, '..');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Metro configuration
|
||||||
|
* https://facebook.github.io/metro/docs/configuration
|
||||||
|
*
|
||||||
|
* @type {import('metro-config').MetroConfig}
|
||||||
|
*/
|
||||||
|
module.exports = getConfig(getDefaultConfig(__dirname), {
|
||||||
|
root,
|
||||||
|
pkg,
|
||||||
|
project: __dirname,
|
||||||
|
});
|
||||||
29
example/package.json
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
{
|
||||||
|
"name": "react-native-pubky-example",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"private": true,
|
||||||
|
"scripts": {
|
||||||
|
"android": "react-native run-android",
|
||||||
|
"ios": "react-native run-ios",
|
||||||
|
"start": "react-native start",
|
||||||
|
"build:android": "react-native build-android --extra-params \"--no-daemon --console=plain -PreactNativeArchitectures=arm64-v8a\"",
|
||||||
|
"build:ios": "cd ios && rm -rf Podfile.lock Pods && pod install && react-native build-ios --scheme PubkyExample --mode Debug --extra-params \"-sdk iphonesimulator CC=clang CPLUSPLUS=clang++ LD=clang LDPLUSPLUS=clang++ GCC_OPTIMIZATION_LEVEL=0 GCC_PRECOMPILE_PREFIX_HEADER=YES ASSETCATALOG_COMPILER_OPTIMIZATION=time DEBUG_INFORMATION_FORMAT=dwarf COMPILER_INDEX_STORE_ENABLE=NO\"",
|
||||||
|
"postinstall": "cd ios && pod install && cd .."
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"react": "18.3.1",
|
||||||
|
"react-native": "0.75.2"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@babel/core": "^7.20.0",
|
||||||
|
"@babel/preset-env": "^7.20.0",
|
||||||
|
"@babel/runtime": "^7.20.0",
|
||||||
|
"@react-native/babel-preset": "0.75.2",
|
||||||
|
"@react-native/metro-config": "0.75.2",
|
||||||
|
"@react-native/typescript-config": "0.75.2",
|
||||||
|
"react-native-builder-bob": "^0.30.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
}
|
||||||
|
}
|
||||||
15
example/react-native.config.js
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
const path = require('path');
|
||||||
|
const pkg = require('../package.json');
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
project: {
|
||||||
|
ios: {
|
||||||
|
automaticPodsInstallation: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
dependencies: {
|
||||||
|
[pkg.name]: {
|
||||||
|
root: path.join(__dirname, '..'),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
37
example/src/App.tsx
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
import { StyleSheet, View, Button } from 'react-native';
|
||||||
|
import { auth } from 'react-native-pubky';
|
||||||
|
|
||||||
|
export default function App() {
|
||||||
|
return (
|
||||||
|
<View style={styles.container}>
|
||||||
|
<Button
|
||||||
|
title={'auth'}
|
||||||
|
onPress={async (): Promise<void> => {
|
||||||
|
try {
|
||||||
|
const res = await auth('pubkyAuthUrl', 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855');
|
||||||
|
if (res.isErr()) {
|
||||||
|
console.log(res.error.message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.log(res.value);
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
container: {
|
||||||
|
flex: 1,
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
},
|
||||||
|
box: {
|
||||||
|
width: 60,
|
||||||
|
height: 60,
|
||||||
|
marginVertical: 20,
|
||||||
|
},
|
||||||
|
});
|
||||||
47
ios/Frameworks/Mobile.xcframework/Info.plist
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>AvailableLibraries</key>
|
||||||
|
<array>
|
||||||
|
<dict>
|
||||||
|
<key>BinaryPath</key>
|
||||||
|
<string>libmobile.a</string>
|
||||||
|
<key>HeadersPath</key>
|
||||||
|
<string>Headers</string>
|
||||||
|
<key>LibraryIdentifier</key>
|
||||||
|
<string>ios-arm64</string>
|
||||||
|
<key>LibraryPath</key>
|
||||||
|
<string>libmobile.a</string>
|
||||||
|
<key>SupportedArchitectures</key>
|
||||||
|
<array>
|
||||||
|
<string>arm64</string>
|
||||||
|
</array>
|
||||||
|
<key>SupportedPlatform</key>
|
||||||
|
<string>ios</string>
|
||||||
|
</dict>
|
||||||
|
<dict>
|
||||||
|
<key>BinaryPath</key>
|
||||||
|
<string>libmobile.a</string>
|
||||||
|
<key>HeadersPath</key>
|
||||||
|
<string>Headers</string>
|
||||||
|
<key>LibraryIdentifier</key>
|
||||||
|
<string>ios-arm64-simulator</string>
|
||||||
|
<key>LibraryPath</key>
|
||||||
|
<string>libmobile.a</string>
|
||||||
|
<key>SupportedArchitectures</key>
|
||||||
|
<array>
|
||||||
|
<string>arm64</string>
|
||||||
|
</array>
|
||||||
|
<key>SupportedPlatform</key>
|
||||||
|
<string>ios</string>
|
||||||
|
<key>SupportedPlatformVariant</key>
|
||||||
|
<string>simulator</string>
|
||||||
|
</dict>
|
||||||
|
</array>
|
||||||
|
<key>CFBundlePackageType</key>
|
||||||
|
<string>XFWK</string>
|
||||||
|
<key>XCFrameworkFormatVersion</key>
|
||||||
|
<string>1.0</string>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
@@ -0,0 +1,194 @@
|
|||||||
|
// This file was autogenerated by some hot garbage in the `uniffi` crate.
|
||||||
|
// Trust me, you don't want to mess with it!
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
// The following structs are used to implement the lowest level
|
||||||
|
// of the FFI, and thus useful to multiple uniffied crates.
|
||||||
|
// We ensure they are declared exactly once, with a header guard, UNIFFI_SHARED_H.
|
||||||
|
#ifdef UNIFFI_SHARED_H
|
||||||
|
// We also try to prevent mixing versions of shared uniffi header structs.
|
||||||
|
// If you add anything to the #else block, you must increment the version suffix in UNIFFI_SHARED_HEADER_V4
|
||||||
|
#ifndef UNIFFI_SHARED_HEADER_V4
|
||||||
|
#error Combining helper code from multiple versions of uniffi is not supported
|
||||||
|
#endif // ndef UNIFFI_SHARED_HEADER_V4
|
||||||
|
#else
|
||||||
|
#define UNIFFI_SHARED_H
|
||||||
|
#define UNIFFI_SHARED_HEADER_V4
|
||||||
|
// ⚠️ Attention: If you change this #else block (ending in `#endif // def UNIFFI_SHARED_H`) you *must* ⚠️
|
||||||
|
// ⚠️ increment the version suffix in all instances of UNIFFI_SHARED_HEADER_V4 in this file. ⚠️
|
||||||
|
|
||||||
|
typedef struct RustBuffer
|
||||||
|
{
|
||||||
|
int32_t capacity;
|
||||||
|
int32_t len;
|
||||||
|
uint8_t *_Nullable data;
|
||||||
|
} RustBuffer;
|
||||||
|
|
||||||
|
typedef int32_t (*ForeignCallback)(uint64_t, int32_t, const uint8_t *_Nonnull, int32_t, RustBuffer *_Nonnull);
|
||||||
|
|
||||||
|
// Task defined in Rust that Swift executes
|
||||||
|
typedef void (*UniFfiRustTaskCallback)(const void * _Nullable, int8_t);
|
||||||
|
|
||||||
|
// Callback to execute Rust tasks using a Swift Task
|
||||||
|
//
|
||||||
|
// Args:
|
||||||
|
// executor: ForeignExecutor lowered into a size_t value
|
||||||
|
// delay: Delay in MS
|
||||||
|
// task: UniFfiRustTaskCallback to call
|
||||||
|
// task_data: data to pass the task callback
|
||||||
|
typedef int8_t (*UniFfiForeignExecutorCallback)(size_t, uint32_t, UniFfiRustTaskCallback _Nullable, const void * _Nullable);
|
||||||
|
|
||||||
|
typedef struct ForeignBytes
|
||||||
|
{
|
||||||
|
int32_t len;
|
||||||
|
const uint8_t *_Nullable data;
|
||||||
|
} ForeignBytes;
|
||||||
|
|
||||||
|
// Error definitions
|
||||||
|
typedef struct RustCallStatus {
|
||||||
|
int8_t code;
|
||||||
|
RustBuffer errorBuf;
|
||||||
|
} RustCallStatus;
|
||||||
|
|
||||||
|
// ⚠️ Attention: If you change this #else block (ending in `#endif // def UNIFFI_SHARED_H`) you *must* ⚠️
|
||||||
|
// ⚠️ increment the version suffix in all instances of UNIFFI_SHARED_HEADER_V4 in this file. ⚠️
|
||||||
|
#endif // def UNIFFI_SHARED_H
|
||||||
|
|
||||||
|
// Continuation callback for UniFFI Futures
|
||||||
|
typedef void (*UniFfiRustFutureContinuation)(void * _Nonnull, int8_t);
|
||||||
|
|
||||||
|
// Scaffolding functions
|
||||||
|
void* _Nonnull uniffi_mobile_fn_func_auth(RustBuffer url, RustBuffer secret_key
|
||||||
|
);
|
||||||
|
RustBuffer uniffi_mobile_fn_func_myexample(RustCallStatus *_Nonnull out_status
|
||||||
|
|
||||||
|
);
|
||||||
|
RustBuffer ffi_mobile_rustbuffer_alloc(int32_t size, RustCallStatus *_Nonnull out_status
|
||||||
|
);
|
||||||
|
RustBuffer ffi_mobile_rustbuffer_from_bytes(ForeignBytes bytes, RustCallStatus *_Nonnull out_status
|
||||||
|
);
|
||||||
|
void ffi_mobile_rustbuffer_free(RustBuffer buf, RustCallStatus *_Nonnull out_status
|
||||||
|
);
|
||||||
|
RustBuffer ffi_mobile_rustbuffer_reserve(RustBuffer buf, int32_t additional, RustCallStatus *_Nonnull out_status
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_continuation_callback_set(UniFfiRustFutureContinuation _Nonnull callback
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_poll_u8(void* _Nonnull handle, void* _Nonnull uniffi_callback
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_cancel_u8(void* _Nonnull handle
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_free_u8(void* _Nonnull handle
|
||||||
|
);
|
||||||
|
uint8_t ffi_mobile_rust_future_complete_u8(void* _Nonnull handle, RustCallStatus *_Nonnull out_status
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_poll_i8(void* _Nonnull handle, void* _Nonnull uniffi_callback
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_cancel_i8(void* _Nonnull handle
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_free_i8(void* _Nonnull handle
|
||||||
|
);
|
||||||
|
int8_t ffi_mobile_rust_future_complete_i8(void* _Nonnull handle, RustCallStatus *_Nonnull out_status
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_poll_u16(void* _Nonnull handle, void* _Nonnull uniffi_callback
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_cancel_u16(void* _Nonnull handle
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_free_u16(void* _Nonnull handle
|
||||||
|
);
|
||||||
|
uint16_t ffi_mobile_rust_future_complete_u16(void* _Nonnull handle, RustCallStatus *_Nonnull out_status
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_poll_i16(void* _Nonnull handle, void* _Nonnull uniffi_callback
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_cancel_i16(void* _Nonnull handle
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_free_i16(void* _Nonnull handle
|
||||||
|
);
|
||||||
|
int16_t ffi_mobile_rust_future_complete_i16(void* _Nonnull handle, RustCallStatus *_Nonnull out_status
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_poll_u32(void* _Nonnull handle, void* _Nonnull uniffi_callback
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_cancel_u32(void* _Nonnull handle
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_free_u32(void* _Nonnull handle
|
||||||
|
);
|
||||||
|
uint32_t ffi_mobile_rust_future_complete_u32(void* _Nonnull handle, RustCallStatus *_Nonnull out_status
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_poll_i32(void* _Nonnull handle, void* _Nonnull uniffi_callback
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_cancel_i32(void* _Nonnull handle
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_free_i32(void* _Nonnull handle
|
||||||
|
);
|
||||||
|
int32_t ffi_mobile_rust_future_complete_i32(void* _Nonnull handle, RustCallStatus *_Nonnull out_status
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_poll_u64(void* _Nonnull handle, void* _Nonnull uniffi_callback
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_cancel_u64(void* _Nonnull handle
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_free_u64(void* _Nonnull handle
|
||||||
|
);
|
||||||
|
uint64_t ffi_mobile_rust_future_complete_u64(void* _Nonnull handle, RustCallStatus *_Nonnull out_status
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_poll_i64(void* _Nonnull handle, void* _Nonnull uniffi_callback
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_cancel_i64(void* _Nonnull handle
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_free_i64(void* _Nonnull handle
|
||||||
|
);
|
||||||
|
int64_t ffi_mobile_rust_future_complete_i64(void* _Nonnull handle, RustCallStatus *_Nonnull out_status
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_poll_f32(void* _Nonnull handle, void* _Nonnull uniffi_callback
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_cancel_f32(void* _Nonnull handle
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_free_f32(void* _Nonnull handle
|
||||||
|
);
|
||||||
|
float ffi_mobile_rust_future_complete_f32(void* _Nonnull handle, RustCallStatus *_Nonnull out_status
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_poll_f64(void* _Nonnull handle, void* _Nonnull uniffi_callback
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_cancel_f64(void* _Nonnull handle
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_free_f64(void* _Nonnull handle
|
||||||
|
);
|
||||||
|
double ffi_mobile_rust_future_complete_f64(void* _Nonnull handle, RustCallStatus *_Nonnull out_status
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_poll_pointer(void* _Nonnull handle, void* _Nonnull uniffi_callback
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_cancel_pointer(void* _Nonnull handle
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_free_pointer(void* _Nonnull handle
|
||||||
|
);
|
||||||
|
void*_Nonnull ffi_mobile_rust_future_complete_pointer(void* _Nonnull handle, RustCallStatus *_Nonnull out_status
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_poll_rust_buffer(void* _Nonnull handle, void* _Nonnull uniffi_callback
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_cancel_rust_buffer(void* _Nonnull handle
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_free_rust_buffer(void* _Nonnull handle
|
||||||
|
);
|
||||||
|
RustBuffer ffi_mobile_rust_future_complete_rust_buffer(void* _Nonnull handle, RustCallStatus *_Nonnull out_status
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_poll_void(void* _Nonnull handle, void* _Nonnull uniffi_callback
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_cancel_void(void* _Nonnull handle
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_free_void(void* _Nonnull handle
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_complete_void(void* _Nonnull handle, RustCallStatus *_Nonnull out_status
|
||||||
|
);
|
||||||
|
uint16_t uniffi_mobile_checksum_func_auth(void
|
||||||
|
|
||||||
|
);
|
||||||
|
uint16_t uniffi_mobile_checksum_func_myexample(void
|
||||||
|
|
||||||
|
);
|
||||||
|
uint32_t ffi_mobile_uniffi_contract_version(void
|
||||||
|
|
||||||
|
);
|
||||||
|
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
// This file was autogenerated by some hot garbage in the `uniffi` crate.
|
||||||
|
// Trust me, you don't want to mess with it!
|
||||||
|
module mobileFFI {
|
||||||
|
header "mobileFFI.h"
|
||||||
|
export *
|
||||||
|
}
|
||||||
194
ios/Frameworks/Mobile.xcframework/ios-arm64/Headers/mobileFFI.h
Normal file
@@ -0,0 +1,194 @@
|
|||||||
|
// This file was autogenerated by some hot garbage in the `uniffi` crate.
|
||||||
|
// Trust me, you don't want to mess with it!
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
// The following structs are used to implement the lowest level
|
||||||
|
// of the FFI, and thus useful to multiple uniffied crates.
|
||||||
|
// We ensure they are declared exactly once, with a header guard, UNIFFI_SHARED_H.
|
||||||
|
#ifdef UNIFFI_SHARED_H
|
||||||
|
// We also try to prevent mixing versions of shared uniffi header structs.
|
||||||
|
// If you add anything to the #else block, you must increment the version suffix in UNIFFI_SHARED_HEADER_V4
|
||||||
|
#ifndef UNIFFI_SHARED_HEADER_V4
|
||||||
|
#error Combining helper code from multiple versions of uniffi is not supported
|
||||||
|
#endif // ndef UNIFFI_SHARED_HEADER_V4
|
||||||
|
#else
|
||||||
|
#define UNIFFI_SHARED_H
|
||||||
|
#define UNIFFI_SHARED_HEADER_V4
|
||||||
|
// ⚠️ Attention: If you change this #else block (ending in `#endif // def UNIFFI_SHARED_H`) you *must* ⚠️
|
||||||
|
// ⚠️ increment the version suffix in all instances of UNIFFI_SHARED_HEADER_V4 in this file. ⚠️
|
||||||
|
|
||||||
|
typedef struct RustBuffer
|
||||||
|
{
|
||||||
|
int32_t capacity;
|
||||||
|
int32_t len;
|
||||||
|
uint8_t *_Nullable data;
|
||||||
|
} RustBuffer;
|
||||||
|
|
||||||
|
typedef int32_t (*ForeignCallback)(uint64_t, int32_t, const uint8_t *_Nonnull, int32_t, RustBuffer *_Nonnull);
|
||||||
|
|
||||||
|
// Task defined in Rust that Swift executes
|
||||||
|
typedef void (*UniFfiRustTaskCallback)(const void * _Nullable, int8_t);
|
||||||
|
|
||||||
|
// Callback to execute Rust tasks using a Swift Task
|
||||||
|
//
|
||||||
|
// Args:
|
||||||
|
// executor: ForeignExecutor lowered into a size_t value
|
||||||
|
// delay: Delay in MS
|
||||||
|
// task: UniFfiRustTaskCallback to call
|
||||||
|
// task_data: data to pass the task callback
|
||||||
|
typedef int8_t (*UniFfiForeignExecutorCallback)(size_t, uint32_t, UniFfiRustTaskCallback _Nullable, const void * _Nullable);
|
||||||
|
|
||||||
|
typedef struct ForeignBytes
|
||||||
|
{
|
||||||
|
int32_t len;
|
||||||
|
const uint8_t *_Nullable data;
|
||||||
|
} ForeignBytes;
|
||||||
|
|
||||||
|
// Error definitions
|
||||||
|
typedef struct RustCallStatus {
|
||||||
|
int8_t code;
|
||||||
|
RustBuffer errorBuf;
|
||||||
|
} RustCallStatus;
|
||||||
|
|
||||||
|
// ⚠️ Attention: If you change this #else block (ending in `#endif // def UNIFFI_SHARED_H`) you *must* ⚠️
|
||||||
|
// ⚠️ increment the version suffix in all instances of UNIFFI_SHARED_HEADER_V4 in this file. ⚠️
|
||||||
|
#endif // def UNIFFI_SHARED_H
|
||||||
|
|
||||||
|
// Continuation callback for UniFFI Futures
|
||||||
|
typedef void (*UniFfiRustFutureContinuation)(void * _Nonnull, int8_t);
|
||||||
|
|
||||||
|
// Scaffolding functions
|
||||||
|
void* _Nonnull uniffi_mobile_fn_func_auth(RustBuffer url, RustBuffer secret_key
|
||||||
|
);
|
||||||
|
RustBuffer uniffi_mobile_fn_func_myexample(RustCallStatus *_Nonnull out_status
|
||||||
|
|
||||||
|
);
|
||||||
|
RustBuffer ffi_mobile_rustbuffer_alloc(int32_t size, RustCallStatus *_Nonnull out_status
|
||||||
|
);
|
||||||
|
RustBuffer ffi_mobile_rustbuffer_from_bytes(ForeignBytes bytes, RustCallStatus *_Nonnull out_status
|
||||||
|
);
|
||||||
|
void ffi_mobile_rustbuffer_free(RustBuffer buf, RustCallStatus *_Nonnull out_status
|
||||||
|
);
|
||||||
|
RustBuffer ffi_mobile_rustbuffer_reserve(RustBuffer buf, int32_t additional, RustCallStatus *_Nonnull out_status
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_continuation_callback_set(UniFfiRustFutureContinuation _Nonnull callback
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_poll_u8(void* _Nonnull handle, void* _Nonnull uniffi_callback
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_cancel_u8(void* _Nonnull handle
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_free_u8(void* _Nonnull handle
|
||||||
|
);
|
||||||
|
uint8_t ffi_mobile_rust_future_complete_u8(void* _Nonnull handle, RustCallStatus *_Nonnull out_status
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_poll_i8(void* _Nonnull handle, void* _Nonnull uniffi_callback
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_cancel_i8(void* _Nonnull handle
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_free_i8(void* _Nonnull handle
|
||||||
|
);
|
||||||
|
int8_t ffi_mobile_rust_future_complete_i8(void* _Nonnull handle, RustCallStatus *_Nonnull out_status
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_poll_u16(void* _Nonnull handle, void* _Nonnull uniffi_callback
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_cancel_u16(void* _Nonnull handle
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_free_u16(void* _Nonnull handle
|
||||||
|
);
|
||||||
|
uint16_t ffi_mobile_rust_future_complete_u16(void* _Nonnull handle, RustCallStatus *_Nonnull out_status
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_poll_i16(void* _Nonnull handle, void* _Nonnull uniffi_callback
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_cancel_i16(void* _Nonnull handle
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_free_i16(void* _Nonnull handle
|
||||||
|
);
|
||||||
|
int16_t ffi_mobile_rust_future_complete_i16(void* _Nonnull handle, RustCallStatus *_Nonnull out_status
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_poll_u32(void* _Nonnull handle, void* _Nonnull uniffi_callback
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_cancel_u32(void* _Nonnull handle
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_free_u32(void* _Nonnull handle
|
||||||
|
);
|
||||||
|
uint32_t ffi_mobile_rust_future_complete_u32(void* _Nonnull handle, RustCallStatus *_Nonnull out_status
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_poll_i32(void* _Nonnull handle, void* _Nonnull uniffi_callback
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_cancel_i32(void* _Nonnull handle
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_free_i32(void* _Nonnull handle
|
||||||
|
);
|
||||||
|
int32_t ffi_mobile_rust_future_complete_i32(void* _Nonnull handle, RustCallStatus *_Nonnull out_status
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_poll_u64(void* _Nonnull handle, void* _Nonnull uniffi_callback
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_cancel_u64(void* _Nonnull handle
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_free_u64(void* _Nonnull handle
|
||||||
|
);
|
||||||
|
uint64_t ffi_mobile_rust_future_complete_u64(void* _Nonnull handle, RustCallStatus *_Nonnull out_status
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_poll_i64(void* _Nonnull handle, void* _Nonnull uniffi_callback
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_cancel_i64(void* _Nonnull handle
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_free_i64(void* _Nonnull handle
|
||||||
|
);
|
||||||
|
int64_t ffi_mobile_rust_future_complete_i64(void* _Nonnull handle, RustCallStatus *_Nonnull out_status
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_poll_f32(void* _Nonnull handle, void* _Nonnull uniffi_callback
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_cancel_f32(void* _Nonnull handle
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_free_f32(void* _Nonnull handle
|
||||||
|
);
|
||||||
|
float ffi_mobile_rust_future_complete_f32(void* _Nonnull handle, RustCallStatus *_Nonnull out_status
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_poll_f64(void* _Nonnull handle, void* _Nonnull uniffi_callback
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_cancel_f64(void* _Nonnull handle
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_free_f64(void* _Nonnull handle
|
||||||
|
);
|
||||||
|
double ffi_mobile_rust_future_complete_f64(void* _Nonnull handle, RustCallStatus *_Nonnull out_status
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_poll_pointer(void* _Nonnull handle, void* _Nonnull uniffi_callback
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_cancel_pointer(void* _Nonnull handle
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_free_pointer(void* _Nonnull handle
|
||||||
|
);
|
||||||
|
void*_Nonnull ffi_mobile_rust_future_complete_pointer(void* _Nonnull handle, RustCallStatus *_Nonnull out_status
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_poll_rust_buffer(void* _Nonnull handle, void* _Nonnull uniffi_callback
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_cancel_rust_buffer(void* _Nonnull handle
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_free_rust_buffer(void* _Nonnull handle
|
||||||
|
);
|
||||||
|
RustBuffer ffi_mobile_rust_future_complete_rust_buffer(void* _Nonnull handle, RustCallStatus *_Nonnull out_status
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_poll_void(void* _Nonnull handle, void* _Nonnull uniffi_callback
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_cancel_void(void* _Nonnull handle
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_free_void(void* _Nonnull handle
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_complete_void(void* _Nonnull handle, RustCallStatus *_Nonnull out_status
|
||||||
|
);
|
||||||
|
uint16_t uniffi_mobile_checksum_func_auth(void
|
||||||
|
|
||||||
|
);
|
||||||
|
uint16_t uniffi_mobile_checksum_func_myexample(void
|
||||||
|
|
||||||
|
);
|
||||||
|
uint32_t ffi_mobile_uniffi_contract_version(void
|
||||||
|
|
||||||
|
);
|
||||||
|
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
// This file was autogenerated by some hot garbage in the `uniffi` crate.
|
||||||
|
// Trust me, you don't want to mess with it!
|
||||||
|
module mobileFFI {
|
||||||
|
header "mobileFFI.h"
|
||||||
|
export *
|
||||||
|
}
|
||||||
BIN
ios/Frameworks/Mobile.xcframework/ios-arm64/libmobile.a
Normal file
2
ios/Pubky-Bridging-Header.h
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
#import <React/RCTBridgeModule.h>
|
||||||
|
#import <React/RCTViewManager.h>
|
||||||
16
ios/Pubky.mm
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
#import <React/RCTBridgeModule.h>
|
||||||
|
|
||||||
|
@interface RCT_EXTERN_MODULE(Pubky, NSObject)
|
||||||
|
|
||||||
|
RCT_EXTERN_METHOD(auth:(NSString *)url
|
||||||
|
secretKey:(NSString *)secretKey
|
||||||
|
withResolver:(RCTPromiseResolveBlock)resolve
|
||||||
|
withRejecter:(RCTPromiseRejectBlock)reject)
|
||||||
|
|
||||||
|
|
||||||
|
+ (BOOL)requiresMainQueueSetup
|
||||||
|
{
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
16
ios/Pubky.swift
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import Foundation
|
||||||
|
|
||||||
|
@objc(Pubky)
|
||||||
|
class Pubky: NSObject {
|
||||||
|
@objc(auth:secretKey:withResolver:withRejecter:)
|
||||||
|
func auth(_ url: String, secretKey: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
||||||
|
Task {
|
||||||
|
do {
|
||||||
|
let result = try await react_native_pubky.auth(url: url, secretKey: secretKey)
|
||||||
|
resolve(result)
|
||||||
|
} catch {
|
||||||
|
reject("auth Error", "Failed to auth", error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
484
ios/mobile.swift
Normal file
@@ -0,0 +1,484 @@
|
|||||||
|
// This file was autogenerated by some hot garbage in the `uniffi` crate.
|
||||||
|
// Trust me, you don't want to mess with it!
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
// Depending on the consumer's build setup, the low-level FFI code
|
||||||
|
// might be in a separate module, or it might be compiled inline into
|
||||||
|
// this module. This is a bit of light hackery to work with both.
|
||||||
|
#if canImport(mobileFFI)
|
||||||
|
import mobileFFI
|
||||||
|
#endif
|
||||||
|
|
||||||
|
fileprivate extension RustBuffer {
|
||||||
|
// Allocate a new buffer, copying the contents of a `UInt8` array.
|
||||||
|
init(bytes: [UInt8]) {
|
||||||
|
let rbuf = bytes.withUnsafeBufferPointer { ptr in
|
||||||
|
RustBuffer.from(ptr)
|
||||||
|
}
|
||||||
|
self.init(capacity: rbuf.capacity, len: rbuf.len, data: rbuf.data)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func from(_ ptr: UnsafeBufferPointer<UInt8>) -> RustBuffer {
|
||||||
|
try! rustCall { ffi_mobile_rustbuffer_from_bytes(ForeignBytes(bufferPointer: ptr), $0) }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Frees the buffer in place.
|
||||||
|
// The buffer must not be used after this is called.
|
||||||
|
func deallocate() {
|
||||||
|
try! rustCall { ffi_mobile_rustbuffer_free(self, $0) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fileprivate extension ForeignBytes {
|
||||||
|
init(bufferPointer: UnsafeBufferPointer<UInt8>) {
|
||||||
|
self.init(len: Int32(bufferPointer.count), data: bufferPointer.baseAddress)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// For every type used in the interface, we provide helper methods for conveniently
|
||||||
|
// lifting and lowering that type from C-compatible data, and for reading and writing
|
||||||
|
// values of that type in a buffer.
|
||||||
|
|
||||||
|
// Helper classes/extensions that don't change.
|
||||||
|
// Someday, this will be in a library of its own.
|
||||||
|
|
||||||
|
fileprivate extension Data {
|
||||||
|
init(rustBuffer: RustBuffer) {
|
||||||
|
// TODO: This copies the buffer. Can we read directly from a
|
||||||
|
// Rust buffer?
|
||||||
|
self.init(bytes: rustBuffer.data!, count: Int(rustBuffer.len))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Define reader functionality. Normally this would be defined in a class or
|
||||||
|
// struct, but we use standalone functions instead in order to make external
|
||||||
|
// types work.
|
||||||
|
//
|
||||||
|
// With external types, one swift source file needs to be able to call the read
|
||||||
|
// method on another source file's FfiConverter, but then what visibility
|
||||||
|
// should Reader have?
|
||||||
|
// - If Reader is fileprivate, then this means the read() must also
|
||||||
|
// be fileprivate, which doesn't work with external types.
|
||||||
|
// - If Reader is internal/public, we'll get compile errors since both source
|
||||||
|
// files will try define the same type.
|
||||||
|
//
|
||||||
|
// Instead, the read() method and these helper functions input a tuple of data
|
||||||
|
|
||||||
|
fileprivate func createReader(data: Data) -> (data: Data, offset: Data.Index) {
|
||||||
|
(data: data, offset: 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reads an integer at the current offset, in big-endian order, and advances
|
||||||
|
// the offset on success. Throws if reading the integer would move the
|
||||||
|
// offset past the end of the buffer.
|
||||||
|
fileprivate func readInt<T: FixedWidthInteger>(_ reader: inout (data: Data, offset: Data.Index)) throws -> T {
|
||||||
|
let range = reader.offset..<reader.offset + MemoryLayout<T>.size
|
||||||
|
guard reader.data.count >= range.upperBound else {
|
||||||
|
throw UniffiInternalError.bufferOverflow
|
||||||
|
}
|
||||||
|
if T.self == UInt8.self {
|
||||||
|
let value = reader.data[reader.offset]
|
||||||
|
reader.offset += 1
|
||||||
|
return value as! T
|
||||||
|
}
|
||||||
|
var value: T = 0
|
||||||
|
let _ = withUnsafeMutableBytes(of: &value, { reader.data.copyBytes(to: $0, from: range)})
|
||||||
|
reader.offset = range.upperBound
|
||||||
|
return value.bigEndian
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reads an arbitrary number of bytes, to be used to read
|
||||||
|
// raw bytes, this is useful when lifting strings
|
||||||
|
fileprivate func readBytes(_ reader: inout (data: Data, offset: Data.Index), count: Int) throws -> Array<UInt8> {
|
||||||
|
let range = reader.offset..<(reader.offset+count)
|
||||||
|
guard reader.data.count >= range.upperBound else {
|
||||||
|
throw UniffiInternalError.bufferOverflow
|
||||||
|
}
|
||||||
|
var value = [UInt8](repeating: 0, count: count)
|
||||||
|
value.withUnsafeMutableBufferPointer({ buffer in
|
||||||
|
reader.data.copyBytes(to: buffer, from: range)
|
||||||
|
})
|
||||||
|
reader.offset = range.upperBound
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reads a float at the current offset.
|
||||||
|
fileprivate func readFloat(_ reader: inout (data: Data, offset: Data.Index)) throws -> Float {
|
||||||
|
return Float(bitPattern: try readInt(&reader))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reads a float at the current offset.
|
||||||
|
fileprivate func readDouble(_ reader: inout (data: Data, offset: Data.Index)) throws -> Double {
|
||||||
|
return Double(bitPattern: try readInt(&reader))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Indicates if the offset has reached the end of the buffer.
|
||||||
|
fileprivate func hasRemaining(_ reader: (data: Data, offset: Data.Index)) -> Bool {
|
||||||
|
return reader.offset < reader.data.count
|
||||||
|
}
|
||||||
|
|
||||||
|
// Define writer functionality. Normally this would be defined in a class or
|
||||||
|
// struct, but we use standalone functions instead in order to make external
|
||||||
|
// types work. See the above discussion on Readers for details.
|
||||||
|
|
||||||
|
fileprivate func createWriter() -> [UInt8] {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
|
||||||
|
fileprivate func writeBytes<S>(_ writer: inout [UInt8], _ byteArr: S) where S: Sequence, S.Element == UInt8 {
|
||||||
|
writer.append(contentsOf: byteArr)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Writes an integer in big-endian order.
|
||||||
|
//
|
||||||
|
// Warning: make sure what you are trying to write
|
||||||
|
// is in the correct type!
|
||||||
|
fileprivate func writeInt<T: FixedWidthInteger>(_ writer: inout [UInt8], _ value: T) {
|
||||||
|
var value = value.bigEndian
|
||||||
|
withUnsafeBytes(of: &value) { writer.append(contentsOf: $0) }
|
||||||
|
}
|
||||||
|
|
||||||
|
fileprivate func writeFloat(_ writer: inout [UInt8], _ value: Float) {
|
||||||
|
writeInt(&writer, value.bitPattern)
|
||||||
|
}
|
||||||
|
|
||||||
|
fileprivate func writeDouble(_ writer: inout [UInt8], _ value: Double) {
|
||||||
|
writeInt(&writer, value.bitPattern)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Protocol for types that transfer other types across the FFI. This is
|
||||||
|
// analogous go the Rust trait of the same name.
|
||||||
|
fileprivate protocol FfiConverter {
|
||||||
|
associatedtype FfiType
|
||||||
|
associatedtype SwiftType
|
||||||
|
|
||||||
|
static func lift(_ value: FfiType) throws -> SwiftType
|
||||||
|
static func lower(_ value: SwiftType) -> FfiType
|
||||||
|
static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> SwiftType
|
||||||
|
static func write(_ value: SwiftType, into buf: inout [UInt8])
|
||||||
|
}
|
||||||
|
|
||||||
|
// Types conforming to `Primitive` pass themselves directly over the FFI.
|
||||||
|
fileprivate protocol FfiConverterPrimitive: FfiConverter where FfiType == SwiftType { }
|
||||||
|
|
||||||
|
extension FfiConverterPrimitive {
|
||||||
|
public static func lift(_ value: FfiType) throws -> SwiftType {
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
|
||||||
|
public static func lower(_ value: SwiftType) -> FfiType {
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Types conforming to `FfiConverterRustBuffer` lift and lower into a `RustBuffer`.
|
||||||
|
// Used for complex types where it's hard to write a custom lift/lower.
|
||||||
|
fileprivate protocol FfiConverterRustBuffer: FfiConverter where FfiType == RustBuffer {}
|
||||||
|
|
||||||
|
extension FfiConverterRustBuffer {
|
||||||
|
public static func lift(_ buf: RustBuffer) throws -> SwiftType {
|
||||||
|
var reader = createReader(data: Data(rustBuffer: buf))
|
||||||
|
let value = try read(from: &reader)
|
||||||
|
if hasRemaining(reader) {
|
||||||
|
throw UniffiInternalError.incompleteData
|
||||||
|
}
|
||||||
|
buf.deallocate()
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
|
||||||
|
public static func lower(_ value: SwiftType) -> RustBuffer {
|
||||||
|
var writer = createWriter()
|
||||||
|
write(value, into: &writer)
|
||||||
|
return RustBuffer(bytes: writer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// An error type for FFI errors. These errors occur at the UniFFI level, not
|
||||||
|
// the library level.
|
||||||
|
fileprivate enum UniffiInternalError: LocalizedError {
|
||||||
|
case bufferOverflow
|
||||||
|
case incompleteData
|
||||||
|
case unexpectedOptionalTag
|
||||||
|
case unexpectedEnumCase
|
||||||
|
case unexpectedNullPointer
|
||||||
|
case unexpectedRustCallStatusCode
|
||||||
|
case unexpectedRustCallError
|
||||||
|
case unexpectedStaleHandle
|
||||||
|
case rustPanic(_ message: String)
|
||||||
|
|
||||||
|
public var errorDescription: String? {
|
||||||
|
switch self {
|
||||||
|
case .bufferOverflow: return "Reading the requested value would read past the end of the buffer"
|
||||||
|
case .incompleteData: return "The buffer still has data after lifting its containing value"
|
||||||
|
case .unexpectedOptionalTag: return "Unexpected optional tag; should be 0 or 1"
|
||||||
|
case .unexpectedEnumCase: return "Raw enum value doesn't match any cases"
|
||||||
|
case .unexpectedNullPointer: return "Raw pointer value was null"
|
||||||
|
case .unexpectedRustCallStatusCode: return "Unexpected RustCallStatus code"
|
||||||
|
case .unexpectedRustCallError: return "CALL_ERROR but no errorClass specified"
|
||||||
|
case .unexpectedStaleHandle: return "The object in the handle map has been dropped already"
|
||||||
|
case let .rustPanic(message): return message
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fileprivate let CALL_SUCCESS: Int8 = 0
|
||||||
|
fileprivate let CALL_ERROR: Int8 = 1
|
||||||
|
fileprivate let CALL_PANIC: Int8 = 2
|
||||||
|
fileprivate let CALL_CANCELLED: Int8 = 3
|
||||||
|
|
||||||
|
fileprivate extension RustCallStatus {
|
||||||
|
init() {
|
||||||
|
self.init(
|
||||||
|
code: CALL_SUCCESS,
|
||||||
|
errorBuf: RustBuffer.init(
|
||||||
|
capacity: 0,
|
||||||
|
len: 0,
|
||||||
|
data: nil
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func rustCall<T>(_ callback: (UnsafeMutablePointer<RustCallStatus>) -> T) throws -> T {
|
||||||
|
try makeRustCall(callback, errorHandler: nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
private func rustCallWithError<T>(
|
||||||
|
_ errorHandler: @escaping (RustBuffer) throws -> Error,
|
||||||
|
_ callback: (UnsafeMutablePointer<RustCallStatus>) -> T) throws -> T {
|
||||||
|
try makeRustCall(callback, errorHandler: errorHandler)
|
||||||
|
}
|
||||||
|
|
||||||
|
private func makeRustCall<T>(
|
||||||
|
_ callback: (UnsafeMutablePointer<RustCallStatus>) -> T,
|
||||||
|
errorHandler: ((RustBuffer) throws -> Error)?
|
||||||
|
) throws -> T {
|
||||||
|
uniffiEnsureInitialized()
|
||||||
|
var callStatus = RustCallStatus.init()
|
||||||
|
let returnedVal = callback(&callStatus)
|
||||||
|
try uniffiCheckCallStatus(callStatus: callStatus, errorHandler: errorHandler)
|
||||||
|
return returnedVal
|
||||||
|
}
|
||||||
|
|
||||||
|
private func uniffiCheckCallStatus(
|
||||||
|
callStatus: RustCallStatus,
|
||||||
|
errorHandler: ((RustBuffer) throws -> Error)?
|
||||||
|
) throws {
|
||||||
|
switch callStatus.code {
|
||||||
|
case CALL_SUCCESS:
|
||||||
|
return
|
||||||
|
|
||||||
|
case CALL_ERROR:
|
||||||
|
if let errorHandler = errorHandler {
|
||||||
|
throw try errorHandler(callStatus.errorBuf)
|
||||||
|
} else {
|
||||||
|
callStatus.errorBuf.deallocate()
|
||||||
|
throw UniffiInternalError.unexpectedRustCallError
|
||||||
|
}
|
||||||
|
|
||||||
|
case CALL_PANIC:
|
||||||
|
// When the rust code sees a panic, it tries to construct a RustBuffer
|
||||||
|
// with the message. But if that code panics, then it just sends back
|
||||||
|
// an empty buffer.
|
||||||
|
if callStatus.errorBuf.len > 0 {
|
||||||
|
throw UniffiInternalError.rustPanic(try FfiConverterString.lift(callStatus.errorBuf))
|
||||||
|
} else {
|
||||||
|
callStatus.errorBuf.deallocate()
|
||||||
|
throw UniffiInternalError.rustPanic("Rust panic")
|
||||||
|
}
|
||||||
|
|
||||||
|
case CALL_CANCELLED:
|
||||||
|
throw CancellationError()
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw UniffiInternalError.unexpectedRustCallStatusCode
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Public interface members begin here.
|
||||||
|
|
||||||
|
|
||||||
|
fileprivate struct FfiConverterString: FfiConverter {
|
||||||
|
typealias SwiftType = String
|
||||||
|
typealias FfiType = RustBuffer
|
||||||
|
|
||||||
|
public static func lift(_ value: RustBuffer) throws -> String {
|
||||||
|
defer {
|
||||||
|
value.deallocate()
|
||||||
|
}
|
||||||
|
if value.data == nil {
|
||||||
|
return String()
|
||||||
|
}
|
||||||
|
let bytes = UnsafeBufferPointer<UInt8>(start: value.data!, count: Int(value.len))
|
||||||
|
return String(bytes: bytes, encoding: String.Encoding.utf8)!
|
||||||
|
}
|
||||||
|
|
||||||
|
public static func lower(_ value: String) -> RustBuffer {
|
||||||
|
return value.utf8CString.withUnsafeBufferPointer { ptr in
|
||||||
|
// The swift string gives us int8_t, we want uint8_t.
|
||||||
|
ptr.withMemoryRebound(to: UInt8.self) { ptr in
|
||||||
|
// The swift string gives us a trailing null byte, we don't want it.
|
||||||
|
let buf = UnsafeBufferPointer(rebasing: ptr.prefix(upTo: ptr.count - 1))
|
||||||
|
return RustBuffer.from(buf)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> String {
|
||||||
|
let len: Int32 = try readInt(&buf)
|
||||||
|
return String(bytes: try readBytes(&buf, count: Int(len)), encoding: String.Encoding.utf8)!
|
||||||
|
}
|
||||||
|
|
||||||
|
public static func write(_ value: String, into buf: inout [UInt8]) {
|
||||||
|
let len = Int32(value.utf8.count)
|
||||||
|
writeInt(&buf, len)
|
||||||
|
writeBytes(&buf, value.utf8)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fileprivate struct FfiConverterSequenceString: FfiConverterRustBuffer {
|
||||||
|
typealias SwiftType = [String]
|
||||||
|
|
||||||
|
public static func write(_ value: [String], into buf: inout [UInt8]) {
|
||||||
|
let len = Int32(value.count)
|
||||||
|
writeInt(&buf, len)
|
||||||
|
for item in value {
|
||||||
|
FfiConverterString.write(item, into: &buf)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> [String] {
|
||||||
|
let len: Int32 = try readInt(&buf)
|
||||||
|
var seq = [String]()
|
||||||
|
seq.reserveCapacity(Int(len))
|
||||||
|
for _ in 0 ..< len {
|
||||||
|
seq.append(try FfiConverterString.read(from: &buf))
|
||||||
|
}
|
||||||
|
return seq
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private let UNIFFI_RUST_FUTURE_POLL_READY: Int8 = 0
|
||||||
|
private let UNIFFI_RUST_FUTURE_POLL_MAYBE_READY: Int8 = 1
|
||||||
|
|
||||||
|
fileprivate func uniffiRustCallAsync<F, T>(
|
||||||
|
rustFutureFunc: () -> UnsafeMutableRawPointer,
|
||||||
|
pollFunc: (UnsafeMutableRawPointer, UnsafeMutableRawPointer) -> (),
|
||||||
|
completeFunc: (UnsafeMutableRawPointer, UnsafeMutablePointer<RustCallStatus>) -> F,
|
||||||
|
freeFunc: (UnsafeMutableRawPointer) -> (),
|
||||||
|
liftFunc: (F) throws -> T,
|
||||||
|
errorHandler: ((RustBuffer) throws -> Error)?
|
||||||
|
) async throws -> T {
|
||||||
|
// Make sure to call uniffiEnsureInitialized() since future creation doesn't have a
|
||||||
|
// RustCallStatus param, so doesn't use makeRustCall()
|
||||||
|
uniffiEnsureInitialized()
|
||||||
|
let rustFuture = rustFutureFunc()
|
||||||
|
defer {
|
||||||
|
freeFunc(rustFuture)
|
||||||
|
}
|
||||||
|
var pollResult: Int8;
|
||||||
|
repeat {
|
||||||
|
pollResult = await withUnsafeContinuation {
|
||||||
|
pollFunc(rustFuture, ContinuationHolder($0).toOpaque())
|
||||||
|
}
|
||||||
|
} while pollResult != UNIFFI_RUST_FUTURE_POLL_READY
|
||||||
|
|
||||||
|
return try liftFunc(makeRustCall(
|
||||||
|
{ completeFunc(rustFuture, $0) },
|
||||||
|
errorHandler: errorHandler
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Callback handlers for an async calls. These are invoked by Rust when the future is ready. They
|
||||||
|
// lift the return value or error and resume the suspended function.
|
||||||
|
fileprivate func uniffiFutureContinuationCallback(ptr: UnsafeMutableRawPointer, pollResult: Int8) {
|
||||||
|
ContinuationHolder.fromOpaque(ptr).resume(pollResult)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wraps UnsafeContinuation in a class so that we can use reference counting when passing it across
|
||||||
|
// the FFI
|
||||||
|
fileprivate class ContinuationHolder {
|
||||||
|
let continuation: UnsafeContinuation<Int8, Never>
|
||||||
|
|
||||||
|
init(_ continuation: UnsafeContinuation<Int8, Never>) {
|
||||||
|
self.continuation = continuation
|
||||||
|
}
|
||||||
|
|
||||||
|
func resume(_ pollResult: Int8) {
|
||||||
|
self.continuation.resume(returning: pollResult)
|
||||||
|
}
|
||||||
|
|
||||||
|
func toOpaque() -> UnsafeMutableRawPointer {
|
||||||
|
return Unmanaged<ContinuationHolder>.passRetained(self).toOpaque()
|
||||||
|
}
|
||||||
|
|
||||||
|
static func fromOpaque(_ ptr: UnsafeRawPointer) -> ContinuationHolder {
|
||||||
|
return Unmanaged<ContinuationHolder>.fromOpaque(ptr).takeRetainedValue()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fileprivate func uniffiInitContinuationCallback() {
|
||||||
|
ffi_mobile_rust_future_continuation_callback_set(uniffiFutureContinuationCallback)
|
||||||
|
}
|
||||||
|
|
||||||
|
public func auth(url: String, secretKey: String) async -> [String] {
|
||||||
|
return try! await uniffiRustCallAsync(
|
||||||
|
rustFutureFunc: {
|
||||||
|
uniffi_mobile_fn_func_auth(
|
||||||
|
FfiConverterString.lower(url),
|
||||||
|
FfiConverterString.lower(secretKey)
|
||||||
|
)
|
||||||
|
},
|
||||||
|
pollFunc: ffi_mobile_rust_future_poll_rust_buffer,
|
||||||
|
completeFunc: ffi_mobile_rust_future_complete_rust_buffer,
|
||||||
|
freeFunc: ffi_mobile_rust_future_free_rust_buffer,
|
||||||
|
liftFunc: FfiConverterSequenceString.lift,
|
||||||
|
errorHandler: nil
|
||||||
|
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public func myexample() -> [String] {
|
||||||
|
return try! FfiConverterSequenceString.lift(
|
||||||
|
try! rustCall() {
|
||||||
|
uniffi_mobile_fn_func_myexample($0)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private enum InitializationResult {
|
||||||
|
case ok
|
||||||
|
case contractVersionMismatch
|
||||||
|
case apiChecksumMismatch
|
||||||
|
}
|
||||||
|
// Use a global variables to perform the versioning checks. Swift ensures that
|
||||||
|
// the code inside is only computed once.
|
||||||
|
private var initializationResult: InitializationResult {
|
||||||
|
// Get the bindings contract version from our ComponentInterface
|
||||||
|
let bindings_contract_version = 24
|
||||||
|
// Get the scaffolding contract version by calling the into the dylib
|
||||||
|
let scaffolding_contract_version = ffi_mobile_uniffi_contract_version()
|
||||||
|
if bindings_contract_version != scaffolding_contract_version {
|
||||||
|
return InitializationResult.contractVersionMismatch
|
||||||
|
}
|
||||||
|
if (uniffi_mobile_checksum_func_auth() != 55720) {
|
||||||
|
return InitializationResult.apiChecksumMismatch
|
||||||
|
}
|
||||||
|
if (uniffi_mobile_checksum_func_myexample() != 65225) {
|
||||||
|
return InitializationResult.apiChecksumMismatch
|
||||||
|
}
|
||||||
|
|
||||||
|
uniffiInitContinuationCallback()
|
||||||
|
return InitializationResult.ok
|
||||||
|
}
|
||||||
|
|
||||||
|
private func uniffiEnsureInitialized() {
|
||||||
|
switch initializationResult {
|
||||||
|
case .ok:
|
||||||
|
break
|
||||||
|
case .contractVersionMismatch:
|
||||||
|
fatalError("UniFFI contract version mismatch: try cleaning and rebuilding your project")
|
||||||
|
case .apiChecksumMismatch:
|
||||||
|
fatalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project")
|
||||||
|
}
|
||||||
|
}
|
||||||
14
lefthook.yml
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
pre-commit:
|
||||||
|
parallel: true
|
||||||
|
commands:
|
||||||
|
lint:
|
||||||
|
glob: "*.{js,ts,jsx,tsx}"
|
||||||
|
run: npx eslint {staged_files}
|
||||||
|
types:
|
||||||
|
glob: "*.{js,ts, jsx, tsx}"
|
||||||
|
run: npx tsc
|
||||||
|
commit-msg:
|
||||||
|
parallel: true
|
||||||
|
commands:
|
||||||
|
commitlint:
|
||||||
|
run: npx commitlint --edit
|
||||||
22951
package-lock.json
generated
Normal file
196
package.json
Normal file
@@ -0,0 +1,196 @@
|
|||||||
|
{
|
||||||
|
"name": "react-native-pubky",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"description": "React Native Implementation of Pubky",
|
||||||
|
"source": "./src/index.tsx",
|
||||||
|
"main": "./lib/commonjs/index.js",
|
||||||
|
"module": "./lib/module/index.js",
|
||||||
|
"react-native": "src/index",
|
||||||
|
"exports": {
|
||||||
|
".": {
|
||||||
|
"import": {
|
||||||
|
"types": "./lib/typescript/module/src/index.d.ts",
|
||||||
|
"default": "./lib/module/index.js"
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"types": "./lib/typescript/commonjs/src/index.d.ts",
|
||||||
|
"default": "./lib/commonjs/index.js"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"src",
|
||||||
|
"lib",
|
||||||
|
"android",
|
||||||
|
"ios",
|
||||||
|
"cpp",
|
||||||
|
"*.podspec",
|
||||||
|
"!ios/build",
|
||||||
|
"!android/build",
|
||||||
|
"!android/gradle",
|
||||||
|
"!android/gradlew",
|
||||||
|
"!android/gradlew.bat",
|
||||||
|
"!android/local.properties",
|
||||||
|
"!**/__tests__",
|
||||||
|
"!**/__fixtures__",
|
||||||
|
"!**/__mocks__",
|
||||||
|
"!**/.*"
|
||||||
|
],
|
||||||
|
"scripts": {
|
||||||
|
"example": "yarn workspace react-native-pubky-example",
|
||||||
|
"test": "jest",
|
||||||
|
"typecheck": "tsc",
|
||||||
|
"lint": "eslint \"**/*.{js,ts,tsx}\"",
|
||||||
|
"clean": "del-cli android/build example/android/build example/android/app/build example/ios/build lib",
|
||||||
|
"prepare": "bob build",
|
||||||
|
"release": "release-it",
|
||||||
|
"reinstall": "npm i && npm run clean && npm run prepare",
|
||||||
|
"update-bindings:ios": "node setup-ios-bindings.js && npm run reinstall",
|
||||||
|
"update-bindings:android": "node setup-android-bindings.js && npm i && npm run clean && npm run prepare",
|
||||||
|
"update-bindings": "npm run update-bindings:ios && npm run update-bindings:android"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"pubky",
|
||||||
|
"react-native",
|
||||||
|
"ios",
|
||||||
|
"android"
|
||||||
|
],
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+https://https://github.com/pubky/react-native-pubky.git"
|
||||||
|
},
|
||||||
|
"author": "coreyphillips <corey@synonym.to> (https://github.com/coreyphillips)",
|
||||||
|
"license": "MIT",
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/pubky/react-native-pubky/issues"
|
||||||
|
},
|
||||||
|
"homepage": "https://github.com/pubky/react-native-pubky#readme",
|
||||||
|
"publishConfig": {
|
||||||
|
"registry": "https://registry.npmjs.org/"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@synonymdev/result": "^0.0.2"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@commitlint/config-conventional": "^17.0.2",
|
||||||
|
"@evilmartians/lefthook": "^1.5.0",
|
||||||
|
"@react-native/eslint-config": "^0.73.1",
|
||||||
|
"@release-it/conventional-changelog": "^5.0.0",
|
||||||
|
"@types/jest": "^29.5.5",
|
||||||
|
"@types/react": "^18.2.44",
|
||||||
|
"commitlint": "^17.0.2",
|
||||||
|
"del-cli": "^5.1.0",
|
||||||
|
"eslint": "^8.51.0",
|
||||||
|
"eslint-config-prettier": "^9.0.0",
|
||||||
|
"eslint-plugin-prettier": "^5.0.1",
|
||||||
|
"jest": "^29.7.0",
|
||||||
|
"prettier": "^3.0.3",
|
||||||
|
"react": "18.3.1",
|
||||||
|
"react-native": "0.75.2",
|
||||||
|
"react-native-builder-bob": "^0.30.2",
|
||||||
|
"release-it": "^15.0.0",
|
||||||
|
"turbo": "^1.10.7",
|
||||||
|
"typescript": "^5.2.2"
|
||||||
|
},
|
||||||
|
"resolutions": {
|
||||||
|
"@types/react": "^18.2.44"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": "*",
|
||||||
|
"react-native": "*"
|
||||||
|
},
|
||||||
|
"workspaces": [
|
||||||
|
"example"
|
||||||
|
],
|
||||||
|
"packageManager": "yarn@3.6.1",
|
||||||
|
"jest": {
|
||||||
|
"preset": "react-native",
|
||||||
|
"modulePathIgnorePatterns": [
|
||||||
|
"<rootDir>/example/node_modules",
|
||||||
|
"<rootDir>/lib/"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"commitlint": {
|
||||||
|
"extends": [
|
||||||
|
"@commitlint/config-conventional"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"release-it": {
|
||||||
|
"git": {
|
||||||
|
"commitMessage": "chore: release ${version}",
|
||||||
|
"tagName": "v${version}"
|
||||||
|
},
|
||||||
|
"npm": {
|
||||||
|
"publish": true
|
||||||
|
},
|
||||||
|
"github": {
|
||||||
|
"release": true
|
||||||
|
},
|
||||||
|
"plugins": {
|
||||||
|
"@release-it/conventional-changelog": {
|
||||||
|
"preset": "angular"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"eslintConfig": {
|
||||||
|
"root": true,
|
||||||
|
"extends": [
|
||||||
|
"@react-native",
|
||||||
|
"prettier"
|
||||||
|
],
|
||||||
|
"rules": {
|
||||||
|
"react/react-in-jsx-scope": "off",
|
||||||
|
"prettier/prettier": [
|
||||||
|
"error",
|
||||||
|
{
|
||||||
|
"quoteProps": "consistent",
|
||||||
|
"singleQuote": true,
|
||||||
|
"tabWidth": 2,
|
||||||
|
"trailingComma": "es5",
|
||||||
|
"useTabs": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"eslintIgnore": [
|
||||||
|
"node_modules/",
|
||||||
|
"lib/"
|
||||||
|
],
|
||||||
|
"prettier": {
|
||||||
|
"quoteProps": "consistent",
|
||||||
|
"singleQuote": true,
|
||||||
|
"tabWidth": 2,
|
||||||
|
"trailingComma": "es5",
|
||||||
|
"useTabs": false
|
||||||
|
},
|
||||||
|
"react-native-builder-bob": {
|
||||||
|
"source": "src",
|
||||||
|
"output": "lib",
|
||||||
|
"targets": [
|
||||||
|
[
|
||||||
|
"commonjs",
|
||||||
|
{
|
||||||
|
"esm": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"module",
|
||||||
|
{
|
||||||
|
"esm": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"typescript",
|
||||||
|
{
|
||||||
|
"project": "tsconfig.build.json",
|
||||||
|
"esm": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"create-react-native-library": {
|
||||||
|
"type": "module-legacy",
|
||||||
|
"languages": "kotlin-swift",
|
||||||
|
"version": "0.41.1"
|
||||||
|
}
|
||||||
|
}
|
||||||
50
react-native-pubky.podspec
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
require "json"
|
||||||
|
|
||||||
|
package = JSON.parse(File.read(File.join(__dir__, "package.json")))
|
||||||
|
folly_compiler_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -Wno-comma -Wno-shorten-64-to-32'
|
||||||
|
|
||||||
|
min_ios_version_supported = '13.4'
|
||||||
|
|
||||||
|
Pod::Spec.new do |s|
|
||||||
|
s.name = "react-native-pubky"
|
||||||
|
s.version = package["version"]
|
||||||
|
s.summary = package["description"]
|
||||||
|
s.homepage = package["homepage"]
|
||||||
|
s.license = package["license"]
|
||||||
|
s.authors = package["author"]
|
||||||
|
|
||||||
|
s.platforms = { :ios => min_ios_version_supported }
|
||||||
|
s.ios.deployment_target = min_ios_version_supported
|
||||||
|
s.source = { :git => "https://github.com/coreyphillips/react-native-pubky.git", :tag => "#{s.version}" }
|
||||||
|
|
||||||
|
s.source_files = "ios/**/*.{h,m,mm,swift}"
|
||||||
|
s.ios.source_files = "ios/**/*.{h,m,mm,swift}"
|
||||||
|
s.ios.vendored_frameworks = "ios/Frameworks/Mobile.xcframework"
|
||||||
|
|
||||||
|
s.pod_target_xcconfig = {
|
||||||
|
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" => "x86_64"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Use install_modules_dependencies helper to install the dependencies if React Native version >=0.71.0.
|
||||||
|
# See https://github.com/facebook/react-native/blob/febf6b7f33fdb4904669f99d795eba4c0f95d7bf/scripts/cocoapods/new_architecture.rb#L79.
|
||||||
|
if respond_to?(:install_modules_dependencies, true)
|
||||||
|
install_modules_dependencies(s)
|
||||||
|
else
|
||||||
|
s.dependency "React-Core"
|
||||||
|
|
||||||
|
# Don't install the dependencies when we run `pod install` in the old architecture.
|
||||||
|
if ENV['RCT_NEW_ARCH_ENABLED'] == '1' then
|
||||||
|
s.compiler_flags = folly_compiler_flags + " -DRCT_NEW_ARCH_ENABLED=1"
|
||||||
|
s.pod_target_xcconfig = {
|
||||||
|
"HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/boost\"",
|
||||||
|
"OTHER_CPLUSPLUSFLAGS" => "-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1",
|
||||||
|
"CLANG_CXX_LANGUAGE_STANDARD" => "c++17"
|
||||||
|
}
|
||||||
|
s.dependency "React-Codegen"
|
||||||
|
s.dependency "RCT-Folly"
|
||||||
|
s.dependency "RCTRequired"
|
||||||
|
s.dependency "RCTTypeSafety"
|
||||||
|
s.dependency "ReactCommon/turbomodule/core"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
3388
rust/Cargo.lock
generated
Normal file
26
rust/Cargo.toml
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
[package]
|
||||||
|
name = "react_native_pubky"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
crate_type = ["cdylib", "staticlib"]
|
||||||
|
name = "mobile"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
uniffi = { version = "0.25.3", features = [ "cli" ] }
|
||||||
|
bitcoin = "0.31.1"
|
||||||
|
bip39 = "2.0.0"
|
||||||
|
secp256k1 = "0.28.2"
|
||||||
|
bip32 = "0.5.1"
|
||||||
|
serde_json = "1.0.114"
|
||||||
|
hex = "0.4.3"
|
||||||
|
sha2 = "0.10.8"
|
||||||
|
serde = { version = "^1.0.209", features = ["derive"] }
|
||||||
|
pkarr = { git = "https://github.com/Pubky/pkarr", branch = "v3", package = "pkarr", features = ["async", "rand"] }
|
||||||
|
pubky = { version = "0.1.0", path = "pubky/pubky" }
|
||||||
|
pubky-common = { version = "0.1.0", path = "pubky/pubky-common" }
|
||||||
|
pubky_homeserver = { version = "0.1.0", path = "pubky/pubky-homeserver" }
|
||||||
|
tokio = "1.40.0"
|
||||||
|
url = "2.5.2"
|
||||||
@@ -0,0 +1,688 @@
|
|||||||
|
// This file was autogenerated by some hot garbage in the `uniffi` crate.
|
||||||
|
// Trust me, you don't want to mess with it!
|
||||||
|
|
||||||
|
@file:Suppress("NAME_SHADOWING")
|
||||||
|
|
||||||
|
package uniffi.mobile;
|
||||||
|
|
||||||
|
// Common helper code.
|
||||||
|
//
|
||||||
|
// Ideally this would live in a separate .kt file where it can be unittested etc
|
||||||
|
// in isolation, and perhaps even published as a re-useable package.
|
||||||
|
//
|
||||||
|
// However, it's important that the details of how this helper code works (e.g. the
|
||||||
|
// way that different builtin types are passed across the FFI) exactly match what's
|
||||||
|
// expected by the Rust code on the other side of the interface. In practice right
|
||||||
|
// now that means coming from the exact some version of `uniffi` that was used to
|
||||||
|
// compile the Rust component. The easiest way to ensure this is to bundle the Kotlin
|
||||||
|
// helpers directly inline like we're doing here.
|
||||||
|
|
||||||
|
import com.sun.jna.Library
|
||||||
|
import com.sun.jna.IntegerType
|
||||||
|
import com.sun.jna.Native
|
||||||
|
import com.sun.jna.Pointer
|
||||||
|
import com.sun.jna.Structure
|
||||||
|
import com.sun.jna.Callback
|
||||||
|
import com.sun.jna.ptr.*
|
||||||
|
import java.nio.ByteBuffer
|
||||||
|
import java.nio.ByteOrder
|
||||||
|
import java.nio.CharBuffer
|
||||||
|
import java.nio.charset.CodingErrorAction
|
||||||
|
import java.util.concurrent.ConcurrentHashMap
|
||||||
|
import kotlin.coroutines.resume
|
||||||
|
import kotlinx.coroutines.CancellableContinuation
|
||||||
|
import kotlinx.coroutines.suspendCancellableCoroutine
|
||||||
|
|
||||||
|
// This is a helper for safely working with byte buffers returned from the Rust code.
|
||||||
|
// A rust-owned buffer is represented by its capacity, its current length, and a
|
||||||
|
// pointer to the underlying data.
|
||||||
|
|
||||||
|
@Structure.FieldOrder("capacity", "len", "data")
|
||||||
|
open class RustBuffer : Structure() {
|
||||||
|
@JvmField var capacity: Int = 0
|
||||||
|
@JvmField var len: Int = 0
|
||||||
|
@JvmField var data: Pointer? = null
|
||||||
|
|
||||||
|
class ByValue: RustBuffer(), Structure.ByValue
|
||||||
|
class ByReference: RustBuffer(), Structure.ByReference
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
internal fun alloc(size: Int = 0) = rustCall() { status ->
|
||||||
|
_UniFFILib.INSTANCE.ffi_mobile_rustbuffer_alloc(size, status)
|
||||||
|
}.also {
|
||||||
|
if(it.data == null) {
|
||||||
|
throw RuntimeException("RustBuffer.alloc() returned null data pointer (size=${size})")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun create(capacity: Int, len: Int, data: Pointer?): RustBuffer.ByValue {
|
||||||
|
var buf = RustBuffer.ByValue()
|
||||||
|
buf.capacity = capacity
|
||||||
|
buf.len = len
|
||||||
|
buf.data = data
|
||||||
|
return buf
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun free(buf: RustBuffer.ByValue) = rustCall() { status ->
|
||||||
|
_UniFFILib.INSTANCE.ffi_mobile_rustbuffer_free(buf, status)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("TooGenericExceptionThrown")
|
||||||
|
fun asByteBuffer() =
|
||||||
|
this.data?.getByteBuffer(0, this.len.toLong())?.also {
|
||||||
|
it.order(ByteOrder.BIG_ENDIAN)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The equivalent of the `*mut RustBuffer` type.
|
||||||
|
* Required for callbacks taking in an out pointer.
|
||||||
|
*
|
||||||
|
* Size is the sum of all values in the struct.
|
||||||
|
*/
|
||||||
|
class RustBufferByReference : ByReference(16) {
|
||||||
|
/**
|
||||||
|
* Set the pointed-to `RustBuffer` to the given value.
|
||||||
|
*/
|
||||||
|
fun setValue(value: RustBuffer.ByValue) {
|
||||||
|
// NOTE: The offsets are as they are in the C-like struct.
|
||||||
|
val pointer = getPointer()
|
||||||
|
pointer.setInt(0, value.capacity)
|
||||||
|
pointer.setInt(4, value.len)
|
||||||
|
pointer.setPointer(8, value.data)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a `RustBuffer.ByValue` from this reference.
|
||||||
|
*/
|
||||||
|
fun getValue(): RustBuffer.ByValue {
|
||||||
|
val pointer = getPointer()
|
||||||
|
val value = RustBuffer.ByValue()
|
||||||
|
value.writeField("capacity", pointer.getInt(0))
|
||||||
|
value.writeField("len", pointer.getInt(4))
|
||||||
|
value.writeField("data", pointer.getPointer(8))
|
||||||
|
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is a helper for safely passing byte references into the rust code.
|
||||||
|
// It's not actually used at the moment, because there aren't many things that you
|
||||||
|
// can take a direct pointer to in the JVM, and if we're going to copy something
|
||||||
|
// then we might as well copy it into a `RustBuffer`. But it's here for API
|
||||||
|
// completeness.
|
||||||
|
|
||||||
|
@Structure.FieldOrder("len", "data")
|
||||||
|
open class ForeignBytes : Structure() {
|
||||||
|
@JvmField var len: Int = 0
|
||||||
|
@JvmField var data: Pointer? = null
|
||||||
|
|
||||||
|
class ByValue : ForeignBytes(), Structure.ByValue
|
||||||
|
}
|
||||||
|
// The FfiConverter interface handles converter types to and from the FFI
|
||||||
|
//
|
||||||
|
// All implementing objects should be public to support external types. When a
|
||||||
|
// type is external we need to import it's FfiConverter.
|
||||||
|
public interface FfiConverter<KotlinType, FfiType> {
|
||||||
|
// Convert an FFI type to a Kotlin type
|
||||||
|
fun lift(value: FfiType): KotlinType
|
||||||
|
|
||||||
|
// Convert an Kotlin type to an FFI type
|
||||||
|
fun lower(value: KotlinType): FfiType
|
||||||
|
|
||||||
|
// Read a Kotlin type from a `ByteBuffer`
|
||||||
|
fun read(buf: ByteBuffer): KotlinType
|
||||||
|
|
||||||
|
// Calculate bytes to allocate when creating a `RustBuffer`
|
||||||
|
//
|
||||||
|
// This must return at least as many bytes as the write() function will
|
||||||
|
// write. It can return more bytes than needed, for example when writing
|
||||||
|
// Strings we can't know the exact bytes needed until we the UTF-8
|
||||||
|
// encoding, so we pessimistically allocate the largest size possible (3
|
||||||
|
// bytes per codepoint). Allocating extra bytes is not really a big deal
|
||||||
|
// because the `RustBuffer` is short-lived.
|
||||||
|
fun allocationSize(value: KotlinType): Int
|
||||||
|
|
||||||
|
// Write a Kotlin type to a `ByteBuffer`
|
||||||
|
fun write(value: KotlinType, buf: ByteBuffer)
|
||||||
|
|
||||||
|
// Lower a value into a `RustBuffer`
|
||||||
|
//
|
||||||
|
// This method lowers a value into a `RustBuffer` rather than the normal
|
||||||
|
// FfiType. It's used by the callback interface code. Callback interface
|
||||||
|
// returns are always serialized into a `RustBuffer` regardless of their
|
||||||
|
// normal FFI type.
|
||||||
|
fun lowerIntoRustBuffer(value: KotlinType): RustBuffer.ByValue {
|
||||||
|
val rbuf = RustBuffer.alloc(allocationSize(value))
|
||||||
|
try {
|
||||||
|
val bbuf = rbuf.data!!.getByteBuffer(0, rbuf.capacity.toLong()).also {
|
||||||
|
it.order(ByteOrder.BIG_ENDIAN)
|
||||||
|
}
|
||||||
|
write(value, bbuf)
|
||||||
|
rbuf.writeField("len", bbuf.position())
|
||||||
|
return rbuf
|
||||||
|
} catch (e: Throwable) {
|
||||||
|
RustBuffer.free(rbuf)
|
||||||
|
throw e
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lift a value from a `RustBuffer`.
|
||||||
|
//
|
||||||
|
// This here mostly because of the symmetry with `lowerIntoRustBuffer()`.
|
||||||
|
// It's currently only used by the `FfiConverterRustBuffer` class below.
|
||||||
|
fun liftFromRustBuffer(rbuf: RustBuffer.ByValue): KotlinType {
|
||||||
|
val byteBuf = rbuf.asByteBuffer()!!
|
||||||
|
try {
|
||||||
|
val item = read(byteBuf)
|
||||||
|
if (byteBuf.hasRemaining()) {
|
||||||
|
throw RuntimeException("junk remaining in buffer after lifting, something is very wrong!!")
|
||||||
|
}
|
||||||
|
return item
|
||||||
|
} finally {
|
||||||
|
RustBuffer.free(rbuf)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FfiConverter that uses `RustBuffer` as the FfiType
|
||||||
|
public interface FfiConverterRustBuffer<KotlinType>: FfiConverter<KotlinType, RustBuffer.ByValue> {
|
||||||
|
override fun lift(value: RustBuffer.ByValue) = liftFromRustBuffer(value)
|
||||||
|
override fun lower(value: KotlinType) = lowerIntoRustBuffer(value)
|
||||||
|
}
|
||||||
|
// A handful of classes and functions to support the generated data structures.
|
||||||
|
// This would be a good candidate for isolating in its own ffi-support lib.
|
||||||
|
// Error runtime.
|
||||||
|
@Structure.FieldOrder("code", "error_buf")
|
||||||
|
internal open class RustCallStatus : Structure() {
|
||||||
|
@JvmField var code: Byte = 0
|
||||||
|
@JvmField var error_buf: RustBuffer.ByValue = RustBuffer.ByValue()
|
||||||
|
|
||||||
|
class ByValue: RustCallStatus(), Structure.ByValue
|
||||||
|
|
||||||
|
fun isSuccess(): Boolean {
|
||||||
|
return code == 0.toByte()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun isError(): Boolean {
|
||||||
|
return code == 1.toByte()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun isPanic(): Boolean {
|
||||||
|
return code == 2.toByte()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class InternalException(message: String) : Exception(message)
|
||||||
|
|
||||||
|
// Each top-level error class has a companion object that can lift the error from the call status's rust buffer
|
||||||
|
interface CallStatusErrorHandler<E> {
|
||||||
|
fun lift(error_buf: RustBuffer.ByValue): E;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helpers for calling Rust
|
||||||
|
// In practice we usually need to be synchronized to call this safely, so it doesn't
|
||||||
|
// synchronize itself
|
||||||
|
|
||||||
|
// Call a rust function that returns a Result<>. Pass in the Error class companion that corresponds to the Err
|
||||||
|
private inline fun <U, E: Exception> rustCallWithError(errorHandler: CallStatusErrorHandler<E>, callback: (RustCallStatus) -> U): U {
|
||||||
|
var status = RustCallStatus();
|
||||||
|
val return_value = callback(status)
|
||||||
|
checkCallStatus(errorHandler, status)
|
||||||
|
return return_value
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check RustCallStatus and throw an error if the call wasn't successful
|
||||||
|
private fun<E: Exception> checkCallStatus(errorHandler: CallStatusErrorHandler<E>, status: RustCallStatus) {
|
||||||
|
if (status.isSuccess()) {
|
||||||
|
return
|
||||||
|
} else if (status.isError()) {
|
||||||
|
throw errorHandler.lift(status.error_buf)
|
||||||
|
} else if (status.isPanic()) {
|
||||||
|
// when the rust code sees a panic, it tries to construct a rustbuffer
|
||||||
|
// with the message. but if that code panics, then it just sends back
|
||||||
|
// an empty buffer.
|
||||||
|
if (status.error_buf.len > 0) {
|
||||||
|
throw InternalException(FfiConverterString.lift(status.error_buf))
|
||||||
|
} else {
|
||||||
|
throw InternalException("Rust panic")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw InternalException("Unknown rust call status: $status.code")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CallStatusErrorHandler implementation for times when we don't expect a CALL_ERROR
|
||||||
|
object NullCallStatusErrorHandler: CallStatusErrorHandler<InternalException> {
|
||||||
|
override fun lift(error_buf: RustBuffer.ByValue): InternalException {
|
||||||
|
RustBuffer.free(error_buf)
|
||||||
|
return InternalException("Unexpected CALL_ERROR")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call a rust function that returns a plain value
|
||||||
|
private inline fun <U> rustCall(callback: (RustCallStatus) -> U): U {
|
||||||
|
return rustCallWithError(NullCallStatusErrorHandler, callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
// IntegerType that matches Rust's `usize` / C's `size_t`
|
||||||
|
public class USize(value: Long = 0) : IntegerType(Native.SIZE_T_SIZE, value, true) {
|
||||||
|
// This is needed to fill in the gaps of IntegerType's implementation of Number for Kotlin.
|
||||||
|
override fun toByte() = toInt().toByte()
|
||||||
|
// Needed until https://youtrack.jetbrains.com/issue/KT-47902 is fixed.
|
||||||
|
@Deprecated("`toInt().toChar()` is deprecated")
|
||||||
|
override fun toChar() = toInt().toChar()
|
||||||
|
override fun toShort() = toInt().toShort()
|
||||||
|
|
||||||
|
fun writeToBuffer(buf: ByteBuffer) {
|
||||||
|
// Make sure we always write usize integers using native byte-order, since they may be
|
||||||
|
// casted to pointer values
|
||||||
|
buf.order(ByteOrder.nativeOrder())
|
||||||
|
try {
|
||||||
|
when (Native.SIZE_T_SIZE) {
|
||||||
|
4 -> buf.putInt(toInt())
|
||||||
|
8 -> buf.putLong(toLong())
|
||||||
|
else -> throw RuntimeException("Invalid SIZE_T_SIZE: ${Native.SIZE_T_SIZE}")
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
buf.order(ByteOrder.BIG_ENDIAN)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
val size: Int
|
||||||
|
get() = Native.SIZE_T_SIZE
|
||||||
|
|
||||||
|
fun readFromBuffer(buf: ByteBuffer) : USize {
|
||||||
|
// Make sure we always read usize integers using native byte-order, since they may be
|
||||||
|
// casted from pointer values
|
||||||
|
buf.order(ByteOrder.nativeOrder())
|
||||||
|
try {
|
||||||
|
return when (Native.SIZE_T_SIZE) {
|
||||||
|
4 -> USize(buf.getInt().toLong())
|
||||||
|
8 -> USize(buf.getLong())
|
||||||
|
else -> throw RuntimeException("Invalid SIZE_T_SIZE: ${Native.SIZE_T_SIZE}")
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
buf.order(ByteOrder.BIG_ENDIAN)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Map handles to objects
|
||||||
|
//
|
||||||
|
// This is used when the Rust code expects an opaque pointer to represent some foreign object.
|
||||||
|
// Normally we would pass a pointer to the object, but JNA doesn't support getting a pointer from an
|
||||||
|
// object reference , nor does it support leaking a reference to Rust.
|
||||||
|
//
|
||||||
|
// Instead, this class maps USize values to objects so that we can pass a pointer-sized type to
|
||||||
|
// Rust when it needs an opaque pointer.
|
||||||
|
//
|
||||||
|
// TODO: refactor callbacks to use this class
|
||||||
|
internal class UniFfiHandleMap<T: Any> {
|
||||||
|
private val map = ConcurrentHashMap<USize, T>()
|
||||||
|
// Use AtomicInteger for our counter, since we may be on a 32-bit system. 4 billion possible
|
||||||
|
// values seems like enough. If somehow we generate 4 billion handles, then this will wrap
|
||||||
|
// around back to zero and we can assume the first handle generated will have been dropped by
|
||||||
|
// then.
|
||||||
|
private val counter = java.util.concurrent.atomic.AtomicInteger(0)
|
||||||
|
|
||||||
|
val size: Int
|
||||||
|
get() = map.size
|
||||||
|
|
||||||
|
fun insert(obj: T): USize {
|
||||||
|
val handle = USize(counter.getAndAdd(1).toLong())
|
||||||
|
map.put(handle, obj)
|
||||||
|
return handle
|
||||||
|
}
|
||||||
|
|
||||||
|
fun get(handle: USize): T? {
|
||||||
|
return map.get(handle)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun remove(handle: USize): T? {
|
||||||
|
return map.remove(handle)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FFI type for Rust future continuations
|
||||||
|
internal interface UniFffiRustFutureContinuationCallbackType : com.sun.jna.Callback {
|
||||||
|
fun callback(continuationHandle: USize, pollResult: Short);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Contains loading, initialization code,
|
||||||
|
// and the FFI Function declarations in a com.sun.jna.Library.
|
||||||
|
@Synchronized
|
||||||
|
private fun findLibraryName(componentName: String): String {
|
||||||
|
val libOverride = System.getProperty("uniffi.component.$componentName.libraryOverride")
|
||||||
|
if (libOverride != null) {
|
||||||
|
return libOverride
|
||||||
|
}
|
||||||
|
return "mobile"
|
||||||
|
}
|
||||||
|
|
||||||
|
private inline fun <reified Lib : Library> loadIndirect(
|
||||||
|
componentName: String
|
||||||
|
): Lib {
|
||||||
|
return Native.load<Lib>(findLibraryName(componentName), Lib::class.java)
|
||||||
|
}
|
||||||
|
|
||||||
|
// A JNA Library to expose the extern-C FFI definitions.
|
||||||
|
// This is an implementation detail which will be called internally by the public API.
|
||||||
|
|
||||||
|
internal interface _UniFFILib : Library {
|
||||||
|
companion object {
|
||||||
|
internal val INSTANCE: _UniFFILib by lazy {
|
||||||
|
loadIndirect<_UniFFILib>(componentName = "mobile")
|
||||||
|
.also { lib: _UniFFILib ->
|
||||||
|
uniffiCheckContractApiVersion(lib)
|
||||||
|
uniffiCheckApiChecksums(lib)
|
||||||
|
uniffiRustFutureContinuationCallback.register(lib)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun uniffi_mobile_fn_func_auth(`url`: RustBuffer.ByValue,`secretKey`: RustBuffer.ByValue,
|
||||||
|
): Pointer
|
||||||
|
fun uniffi_mobile_fn_func_myexample(_uniffi_out_err: RustCallStatus,
|
||||||
|
): RustBuffer.ByValue
|
||||||
|
fun ffi_mobile_rustbuffer_alloc(`size`: Int,_uniffi_out_err: RustCallStatus,
|
||||||
|
): RustBuffer.ByValue
|
||||||
|
fun ffi_mobile_rustbuffer_from_bytes(`bytes`: ForeignBytes.ByValue,_uniffi_out_err: RustCallStatus,
|
||||||
|
): RustBuffer.ByValue
|
||||||
|
fun ffi_mobile_rustbuffer_free(`buf`: RustBuffer.ByValue,_uniffi_out_err: RustCallStatus,
|
||||||
|
): Unit
|
||||||
|
fun ffi_mobile_rustbuffer_reserve(`buf`: RustBuffer.ByValue,`additional`: Int,_uniffi_out_err: RustCallStatus,
|
||||||
|
): RustBuffer.ByValue
|
||||||
|
fun ffi_mobile_rust_future_continuation_callback_set(`callback`: UniFffiRustFutureContinuationCallbackType,
|
||||||
|
): Unit
|
||||||
|
fun ffi_mobile_rust_future_poll_u8(`handle`: Pointer,`uniffiCallback`: USize,
|
||||||
|
): Unit
|
||||||
|
fun ffi_mobile_rust_future_cancel_u8(`handle`: Pointer,
|
||||||
|
): Unit
|
||||||
|
fun ffi_mobile_rust_future_free_u8(`handle`: Pointer,
|
||||||
|
): Unit
|
||||||
|
fun ffi_mobile_rust_future_complete_u8(`handle`: Pointer,_uniffi_out_err: RustCallStatus,
|
||||||
|
): Byte
|
||||||
|
fun ffi_mobile_rust_future_poll_i8(`handle`: Pointer,`uniffiCallback`: USize,
|
||||||
|
): Unit
|
||||||
|
fun ffi_mobile_rust_future_cancel_i8(`handle`: Pointer,
|
||||||
|
): Unit
|
||||||
|
fun ffi_mobile_rust_future_free_i8(`handle`: Pointer,
|
||||||
|
): Unit
|
||||||
|
fun ffi_mobile_rust_future_complete_i8(`handle`: Pointer,_uniffi_out_err: RustCallStatus,
|
||||||
|
): Byte
|
||||||
|
fun ffi_mobile_rust_future_poll_u16(`handle`: Pointer,`uniffiCallback`: USize,
|
||||||
|
): Unit
|
||||||
|
fun ffi_mobile_rust_future_cancel_u16(`handle`: Pointer,
|
||||||
|
): Unit
|
||||||
|
fun ffi_mobile_rust_future_free_u16(`handle`: Pointer,
|
||||||
|
): Unit
|
||||||
|
fun ffi_mobile_rust_future_complete_u16(`handle`: Pointer,_uniffi_out_err: RustCallStatus,
|
||||||
|
): Short
|
||||||
|
fun ffi_mobile_rust_future_poll_i16(`handle`: Pointer,`uniffiCallback`: USize,
|
||||||
|
): Unit
|
||||||
|
fun ffi_mobile_rust_future_cancel_i16(`handle`: Pointer,
|
||||||
|
): Unit
|
||||||
|
fun ffi_mobile_rust_future_free_i16(`handle`: Pointer,
|
||||||
|
): Unit
|
||||||
|
fun ffi_mobile_rust_future_complete_i16(`handle`: Pointer,_uniffi_out_err: RustCallStatus,
|
||||||
|
): Short
|
||||||
|
fun ffi_mobile_rust_future_poll_u32(`handle`: Pointer,`uniffiCallback`: USize,
|
||||||
|
): Unit
|
||||||
|
fun ffi_mobile_rust_future_cancel_u32(`handle`: Pointer,
|
||||||
|
): Unit
|
||||||
|
fun ffi_mobile_rust_future_free_u32(`handle`: Pointer,
|
||||||
|
): Unit
|
||||||
|
fun ffi_mobile_rust_future_complete_u32(`handle`: Pointer,_uniffi_out_err: RustCallStatus,
|
||||||
|
): Int
|
||||||
|
fun ffi_mobile_rust_future_poll_i32(`handle`: Pointer,`uniffiCallback`: USize,
|
||||||
|
): Unit
|
||||||
|
fun ffi_mobile_rust_future_cancel_i32(`handle`: Pointer,
|
||||||
|
): Unit
|
||||||
|
fun ffi_mobile_rust_future_free_i32(`handle`: Pointer,
|
||||||
|
): Unit
|
||||||
|
fun ffi_mobile_rust_future_complete_i32(`handle`: Pointer,_uniffi_out_err: RustCallStatus,
|
||||||
|
): Int
|
||||||
|
fun ffi_mobile_rust_future_poll_u64(`handle`: Pointer,`uniffiCallback`: USize,
|
||||||
|
): Unit
|
||||||
|
fun ffi_mobile_rust_future_cancel_u64(`handle`: Pointer,
|
||||||
|
): Unit
|
||||||
|
fun ffi_mobile_rust_future_free_u64(`handle`: Pointer,
|
||||||
|
): Unit
|
||||||
|
fun ffi_mobile_rust_future_complete_u64(`handle`: Pointer,_uniffi_out_err: RustCallStatus,
|
||||||
|
): Long
|
||||||
|
fun ffi_mobile_rust_future_poll_i64(`handle`: Pointer,`uniffiCallback`: USize,
|
||||||
|
): Unit
|
||||||
|
fun ffi_mobile_rust_future_cancel_i64(`handle`: Pointer,
|
||||||
|
): Unit
|
||||||
|
fun ffi_mobile_rust_future_free_i64(`handle`: Pointer,
|
||||||
|
): Unit
|
||||||
|
fun ffi_mobile_rust_future_complete_i64(`handle`: Pointer,_uniffi_out_err: RustCallStatus,
|
||||||
|
): Long
|
||||||
|
fun ffi_mobile_rust_future_poll_f32(`handle`: Pointer,`uniffiCallback`: USize,
|
||||||
|
): Unit
|
||||||
|
fun ffi_mobile_rust_future_cancel_f32(`handle`: Pointer,
|
||||||
|
): Unit
|
||||||
|
fun ffi_mobile_rust_future_free_f32(`handle`: Pointer,
|
||||||
|
): Unit
|
||||||
|
fun ffi_mobile_rust_future_complete_f32(`handle`: Pointer,_uniffi_out_err: RustCallStatus,
|
||||||
|
): Float
|
||||||
|
fun ffi_mobile_rust_future_poll_f64(`handle`: Pointer,`uniffiCallback`: USize,
|
||||||
|
): Unit
|
||||||
|
fun ffi_mobile_rust_future_cancel_f64(`handle`: Pointer,
|
||||||
|
): Unit
|
||||||
|
fun ffi_mobile_rust_future_free_f64(`handle`: Pointer,
|
||||||
|
): Unit
|
||||||
|
fun ffi_mobile_rust_future_complete_f64(`handle`: Pointer,_uniffi_out_err: RustCallStatus,
|
||||||
|
): Double
|
||||||
|
fun ffi_mobile_rust_future_poll_pointer(`handle`: Pointer,`uniffiCallback`: USize,
|
||||||
|
): Unit
|
||||||
|
fun ffi_mobile_rust_future_cancel_pointer(`handle`: Pointer,
|
||||||
|
): Unit
|
||||||
|
fun ffi_mobile_rust_future_free_pointer(`handle`: Pointer,
|
||||||
|
): Unit
|
||||||
|
fun ffi_mobile_rust_future_complete_pointer(`handle`: Pointer,_uniffi_out_err: RustCallStatus,
|
||||||
|
): Pointer
|
||||||
|
fun ffi_mobile_rust_future_poll_rust_buffer(`handle`: Pointer,`uniffiCallback`: USize,
|
||||||
|
): Unit
|
||||||
|
fun ffi_mobile_rust_future_cancel_rust_buffer(`handle`: Pointer,
|
||||||
|
): Unit
|
||||||
|
fun ffi_mobile_rust_future_free_rust_buffer(`handle`: Pointer,
|
||||||
|
): Unit
|
||||||
|
fun ffi_mobile_rust_future_complete_rust_buffer(`handle`: Pointer,_uniffi_out_err: RustCallStatus,
|
||||||
|
): RustBuffer.ByValue
|
||||||
|
fun ffi_mobile_rust_future_poll_void(`handle`: Pointer,`uniffiCallback`: USize,
|
||||||
|
): Unit
|
||||||
|
fun ffi_mobile_rust_future_cancel_void(`handle`: Pointer,
|
||||||
|
): Unit
|
||||||
|
fun ffi_mobile_rust_future_free_void(`handle`: Pointer,
|
||||||
|
): Unit
|
||||||
|
fun ffi_mobile_rust_future_complete_void(`handle`: Pointer,_uniffi_out_err: RustCallStatus,
|
||||||
|
): Unit
|
||||||
|
fun uniffi_mobile_checksum_func_auth(
|
||||||
|
): Short
|
||||||
|
fun uniffi_mobile_checksum_func_myexample(
|
||||||
|
): Short
|
||||||
|
fun ffi_mobile_uniffi_contract_version(
|
||||||
|
): Int
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun uniffiCheckContractApiVersion(lib: _UniFFILib) {
|
||||||
|
// Get the bindings contract version from our ComponentInterface
|
||||||
|
val bindings_contract_version = 24
|
||||||
|
// Get the scaffolding contract version by calling the into the dylib
|
||||||
|
val scaffolding_contract_version = lib.ffi_mobile_uniffi_contract_version()
|
||||||
|
if (bindings_contract_version != scaffolding_contract_version) {
|
||||||
|
throw RuntimeException("UniFFI contract version mismatch: try cleaning and rebuilding your project")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("UNUSED_PARAMETER")
|
||||||
|
private fun uniffiCheckApiChecksums(lib: _UniFFILib) {
|
||||||
|
if (lib.uniffi_mobile_checksum_func_auth() != 55720.toShort()) {
|
||||||
|
throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project")
|
||||||
|
}
|
||||||
|
if (lib.uniffi_mobile_checksum_func_myexample() != 65225.toShort()) {
|
||||||
|
throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Async support
|
||||||
|
// Async return type handlers
|
||||||
|
|
||||||
|
internal const val UNIFFI_RUST_FUTURE_POLL_READY = 0.toShort()
|
||||||
|
internal const val UNIFFI_RUST_FUTURE_POLL_MAYBE_READY = 1.toShort()
|
||||||
|
|
||||||
|
internal val uniffiContinuationHandleMap = UniFfiHandleMap<CancellableContinuation<Short>>()
|
||||||
|
|
||||||
|
// FFI type for Rust future continuations
|
||||||
|
internal object uniffiRustFutureContinuationCallback: UniFffiRustFutureContinuationCallbackType {
|
||||||
|
override fun callback(continuationHandle: USize, pollResult: Short) {
|
||||||
|
uniffiContinuationHandleMap.remove(continuationHandle)?.resume(pollResult)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun register(lib: _UniFFILib) {
|
||||||
|
lib.ffi_mobile_rust_future_continuation_callback_set(this)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal suspend fun<T, F, E: Exception> uniffiRustCallAsync(
|
||||||
|
rustFuture: Pointer,
|
||||||
|
pollFunc: (Pointer, USize) -> Unit,
|
||||||
|
completeFunc: (Pointer, RustCallStatus) -> F,
|
||||||
|
freeFunc: (Pointer) -> Unit,
|
||||||
|
liftFunc: (F) -> T,
|
||||||
|
errorHandler: CallStatusErrorHandler<E>
|
||||||
|
): T {
|
||||||
|
try {
|
||||||
|
do {
|
||||||
|
val pollResult = suspendCancellableCoroutine<Short> { continuation ->
|
||||||
|
pollFunc(
|
||||||
|
rustFuture,
|
||||||
|
uniffiContinuationHandleMap.insert(continuation)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} while (pollResult != UNIFFI_RUST_FUTURE_POLL_READY);
|
||||||
|
|
||||||
|
return liftFunc(
|
||||||
|
rustCallWithError(errorHandler, { status -> completeFunc(rustFuture, status) })
|
||||||
|
)
|
||||||
|
} finally {
|
||||||
|
freeFunc(rustFuture)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Public interface members begin here.
|
||||||
|
|
||||||
|
|
||||||
|
public object FfiConverterString: FfiConverter<String, RustBuffer.ByValue> {
|
||||||
|
// Note: we don't inherit from FfiConverterRustBuffer, because we use a
|
||||||
|
// special encoding when lowering/lifting. We can use `RustBuffer.len` to
|
||||||
|
// store our length and avoid writing it out to the buffer.
|
||||||
|
override fun lift(value: RustBuffer.ByValue): String {
|
||||||
|
try {
|
||||||
|
val byteArr = ByteArray(value.len)
|
||||||
|
value.asByteBuffer()!!.get(byteArr)
|
||||||
|
return byteArr.toString(Charsets.UTF_8)
|
||||||
|
} finally {
|
||||||
|
RustBuffer.free(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun read(buf: ByteBuffer): String {
|
||||||
|
val len = buf.getInt()
|
||||||
|
val byteArr = ByteArray(len)
|
||||||
|
buf.get(byteArr)
|
||||||
|
return byteArr.toString(Charsets.UTF_8)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun toUtf8(value: String): ByteBuffer {
|
||||||
|
// Make sure we don't have invalid UTF-16, check for lone surrogates.
|
||||||
|
return Charsets.UTF_8.newEncoder().run {
|
||||||
|
onMalformedInput(CodingErrorAction.REPORT)
|
||||||
|
encode(CharBuffer.wrap(value))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun lower(value: String): RustBuffer.ByValue {
|
||||||
|
val byteBuf = toUtf8(value)
|
||||||
|
// Ideally we'd pass these bytes to `ffi_bytebuffer_from_bytes`, but doing so would require us
|
||||||
|
// to copy them into a JNA `Memory`. So we might as well directly copy them into a `RustBuffer`.
|
||||||
|
val rbuf = RustBuffer.alloc(byteBuf.limit())
|
||||||
|
rbuf.asByteBuffer()!!.put(byteBuf)
|
||||||
|
return rbuf
|
||||||
|
}
|
||||||
|
|
||||||
|
// We aren't sure exactly how many bytes our string will be once it's UTF-8
|
||||||
|
// encoded. Allocate 3 bytes per UTF-16 code unit which will always be
|
||||||
|
// enough.
|
||||||
|
override fun allocationSize(value: String): Int {
|
||||||
|
val sizeForLength = 4
|
||||||
|
val sizeForString = value.length * 3
|
||||||
|
return sizeForLength + sizeForString
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun write(value: String, buf: ByteBuffer) {
|
||||||
|
val byteBuf = toUtf8(value)
|
||||||
|
buf.putInt(byteBuf.limit())
|
||||||
|
buf.put(byteBuf)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public object FfiConverterSequenceString: FfiConverterRustBuffer<List<String>> {
|
||||||
|
override fun read(buf: ByteBuffer): List<String> {
|
||||||
|
val len = buf.getInt()
|
||||||
|
return List<String>(len) {
|
||||||
|
FfiConverterString.read(buf)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun allocationSize(value: List<String>): Int {
|
||||||
|
val sizeForLength = 4
|
||||||
|
val sizeForItems = value.map { FfiConverterString.allocationSize(it) }.sum()
|
||||||
|
return sizeForLength + sizeForItems
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun write(value: List<String>, buf: ByteBuffer) {
|
||||||
|
buf.putInt(value.size)
|
||||||
|
value.forEach {
|
||||||
|
FfiConverterString.write(it, buf)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Suppress("ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE")
|
||||||
|
suspend fun `auth`(`url`: String, `secretKey`: String) : List<String> {
|
||||||
|
return uniffiRustCallAsync(
|
||||||
|
_UniFFILib.INSTANCE.uniffi_mobile_fn_func_auth(FfiConverterString.lower(`url`),FfiConverterString.lower(`secretKey`),),
|
||||||
|
{ future, continuation -> _UniFFILib.INSTANCE.ffi_mobile_rust_future_poll_rust_buffer(future, continuation) },
|
||||||
|
{ future, continuation -> _UniFFILib.INSTANCE.ffi_mobile_rust_future_complete_rust_buffer(future, continuation) },
|
||||||
|
{ future -> _UniFFILib.INSTANCE.ffi_mobile_rust_future_free_rust_buffer(future) },
|
||||||
|
// lift function
|
||||||
|
{ FfiConverterSequenceString.lift(it) },
|
||||||
|
// Error FFI converter
|
||||||
|
NullCallStatusErrorHandler,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun `myexample`(): List<String> {
|
||||||
|
return FfiConverterSequenceString.lift(
|
||||||
|
rustCall() { _status ->
|
||||||
|
_UniFFILib.INSTANCE.uniffi_mobile_fn_func_myexample(_status)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
BIN
rust/app/src/main/jniLibs/arm64-v8a/libmobile.so
Executable file
BIN
rust/app/src/main/jniLibs/armeabi-v7a/libmobile.so
Executable file
BIN
rust/app/src/main/jniLibs/x86/libmobile.so
Executable file
BIN
rust/app/src/main/jniLibs/x86_64/libmobile.so
Executable file
484
rust/bindings/mobile.swift
Normal file
@@ -0,0 +1,484 @@
|
|||||||
|
// This file was autogenerated by some hot garbage in the `uniffi` crate.
|
||||||
|
// Trust me, you don't want to mess with it!
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
// Depending on the consumer's build setup, the low-level FFI code
|
||||||
|
// might be in a separate module, or it might be compiled inline into
|
||||||
|
// this module. This is a bit of light hackery to work with both.
|
||||||
|
#if canImport(mobileFFI)
|
||||||
|
import mobileFFI
|
||||||
|
#endif
|
||||||
|
|
||||||
|
fileprivate extension RustBuffer {
|
||||||
|
// Allocate a new buffer, copying the contents of a `UInt8` array.
|
||||||
|
init(bytes: [UInt8]) {
|
||||||
|
let rbuf = bytes.withUnsafeBufferPointer { ptr in
|
||||||
|
RustBuffer.from(ptr)
|
||||||
|
}
|
||||||
|
self.init(capacity: rbuf.capacity, len: rbuf.len, data: rbuf.data)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func from(_ ptr: UnsafeBufferPointer<UInt8>) -> RustBuffer {
|
||||||
|
try! rustCall { ffi_mobile_rustbuffer_from_bytes(ForeignBytes(bufferPointer: ptr), $0) }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Frees the buffer in place.
|
||||||
|
// The buffer must not be used after this is called.
|
||||||
|
func deallocate() {
|
||||||
|
try! rustCall { ffi_mobile_rustbuffer_free(self, $0) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fileprivate extension ForeignBytes {
|
||||||
|
init(bufferPointer: UnsafeBufferPointer<UInt8>) {
|
||||||
|
self.init(len: Int32(bufferPointer.count), data: bufferPointer.baseAddress)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// For every type used in the interface, we provide helper methods for conveniently
|
||||||
|
// lifting and lowering that type from C-compatible data, and for reading and writing
|
||||||
|
// values of that type in a buffer.
|
||||||
|
|
||||||
|
// Helper classes/extensions that don't change.
|
||||||
|
// Someday, this will be in a library of its own.
|
||||||
|
|
||||||
|
fileprivate extension Data {
|
||||||
|
init(rustBuffer: RustBuffer) {
|
||||||
|
// TODO: This copies the buffer. Can we read directly from a
|
||||||
|
// Rust buffer?
|
||||||
|
self.init(bytes: rustBuffer.data!, count: Int(rustBuffer.len))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Define reader functionality. Normally this would be defined in a class or
|
||||||
|
// struct, but we use standalone functions instead in order to make external
|
||||||
|
// types work.
|
||||||
|
//
|
||||||
|
// With external types, one swift source file needs to be able to call the read
|
||||||
|
// method on another source file's FfiConverter, but then what visibility
|
||||||
|
// should Reader have?
|
||||||
|
// - If Reader is fileprivate, then this means the read() must also
|
||||||
|
// be fileprivate, which doesn't work with external types.
|
||||||
|
// - If Reader is internal/public, we'll get compile errors since both source
|
||||||
|
// files will try define the same type.
|
||||||
|
//
|
||||||
|
// Instead, the read() method and these helper functions input a tuple of data
|
||||||
|
|
||||||
|
fileprivate func createReader(data: Data) -> (data: Data, offset: Data.Index) {
|
||||||
|
(data: data, offset: 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reads an integer at the current offset, in big-endian order, and advances
|
||||||
|
// the offset on success. Throws if reading the integer would move the
|
||||||
|
// offset past the end of the buffer.
|
||||||
|
fileprivate func readInt<T: FixedWidthInteger>(_ reader: inout (data: Data, offset: Data.Index)) throws -> T {
|
||||||
|
let range = reader.offset..<reader.offset + MemoryLayout<T>.size
|
||||||
|
guard reader.data.count >= range.upperBound else {
|
||||||
|
throw UniffiInternalError.bufferOverflow
|
||||||
|
}
|
||||||
|
if T.self == UInt8.self {
|
||||||
|
let value = reader.data[reader.offset]
|
||||||
|
reader.offset += 1
|
||||||
|
return value as! T
|
||||||
|
}
|
||||||
|
var value: T = 0
|
||||||
|
let _ = withUnsafeMutableBytes(of: &value, { reader.data.copyBytes(to: $0, from: range)})
|
||||||
|
reader.offset = range.upperBound
|
||||||
|
return value.bigEndian
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reads an arbitrary number of bytes, to be used to read
|
||||||
|
// raw bytes, this is useful when lifting strings
|
||||||
|
fileprivate func readBytes(_ reader: inout (data: Data, offset: Data.Index), count: Int) throws -> Array<UInt8> {
|
||||||
|
let range = reader.offset..<(reader.offset+count)
|
||||||
|
guard reader.data.count >= range.upperBound else {
|
||||||
|
throw UniffiInternalError.bufferOverflow
|
||||||
|
}
|
||||||
|
var value = [UInt8](repeating: 0, count: count)
|
||||||
|
value.withUnsafeMutableBufferPointer({ buffer in
|
||||||
|
reader.data.copyBytes(to: buffer, from: range)
|
||||||
|
})
|
||||||
|
reader.offset = range.upperBound
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reads a float at the current offset.
|
||||||
|
fileprivate func readFloat(_ reader: inout (data: Data, offset: Data.Index)) throws -> Float {
|
||||||
|
return Float(bitPattern: try readInt(&reader))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reads a float at the current offset.
|
||||||
|
fileprivate func readDouble(_ reader: inout (data: Data, offset: Data.Index)) throws -> Double {
|
||||||
|
return Double(bitPattern: try readInt(&reader))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Indicates if the offset has reached the end of the buffer.
|
||||||
|
fileprivate func hasRemaining(_ reader: (data: Data, offset: Data.Index)) -> Bool {
|
||||||
|
return reader.offset < reader.data.count
|
||||||
|
}
|
||||||
|
|
||||||
|
// Define writer functionality. Normally this would be defined in a class or
|
||||||
|
// struct, but we use standalone functions instead in order to make external
|
||||||
|
// types work. See the above discussion on Readers for details.
|
||||||
|
|
||||||
|
fileprivate func createWriter() -> [UInt8] {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
|
||||||
|
fileprivate func writeBytes<S>(_ writer: inout [UInt8], _ byteArr: S) where S: Sequence, S.Element == UInt8 {
|
||||||
|
writer.append(contentsOf: byteArr)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Writes an integer in big-endian order.
|
||||||
|
//
|
||||||
|
// Warning: make sure what you are trying to write
|
||||||
|
// is in the correct type!
|
||||||
|
fileprivate func writeInt<T: FixedWidthInteger>(_ writer: inout [UInt8], _ value: T) {
|
||||||
|
var value = value.bigEndian
|
||||||
|
withUnsafeBytes(of: &value) { writer.append(contentsOf: $0) }
|
||||||
|
}
|
||||||
|
|
||||||
|
fileprivate func writeFloat(_ writer: inout [UInt8], _ value: Float) {
|
||||||
|
writeInt(&writer, value.bitPattern)
|
||||||
|
}
|
||||||
|
|
||||||
|
fileprivate func writeDouble(_ writer: inout [UInt8], _ value: Double) {
|
||||||
|
writeInt(&writer, value.bitPattern)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Protocol for types that transfer other types across the FFI. This is
|
||||||
|
// analogous go the Rust trait of the same name.
|
||||||
|
fileprivate protocol FfiConverter {
|
||||||
|
associatedtype FfiType
|
||||||
|
associatedtype SwiftType
|
||||||
|
|
||||||
|
static func lift(_ value: FfiType) throws -> SwiftType
|
||||||
|
static func lower(_ value: SwiftType) -> FfiType
|
||||||
|
static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> SwiftType
|
||||||
|
static func write(_ value: SwiftType, into buf: inout [UInt8])
|
||||||
|
}
|
||||||
|
|
||||||
|
// Types conforming to `Primitive` pass themselves directly over the FFI.
|
||||||
|
fileprivate protocol FfiConverterPrimitive: FfiConverter where FfiType == SwiftType { }
|
||||||
|
|
||||||
|
extension FfiConverterPrimitive {
|
||||||
|
public static func lift(_ value: FfiType) throws -> SwiftType {
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
|
||||||
|
public static func lower(_ value: SwiftType) -> FfiType {
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Types conforming to `FfiConverterRustBuffer` lift and lower into a `RustBuffer`.
|
||||||
|
// Used for complex types where it's hard to write a custom lift/lower.
|
||||||
|
fileprivate protocol FfiConverterRustBuffer: FfiConverter where FfiType == RustBuffer {}
|
||||||
|
|
||||||
|
extension FfiConverterRustBuffer {
|
||||||
|
public static func lift(_ buf: RustBuffer) throws -> SwiftType {
|
||||||
|
var reader = createReader(data: Data(rustBuffer: buf))
|
||||||
|
let value = try read(from: &reader)
|
||||||
|
if hasRemaining(reader) {
|
||||||
|
throw UniffiInternalError.incompleteData
|
||||||
|
}
|
||||||
|
buf.deallocate()
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
|
||||||
|
public static func lower(_ value: SwiftType) -> RustBuffer {
|
||||||
|
var writer = createWriter()
|
||||||
|
write(value, into: &writer)
|
||||||
|
return RustBuffer(bytes: writer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// An error type for FFI errors. These errors occur at the UniFFI level, not
|
||||||
|
// the library level.
|
||||||
|
fileprivate enum UniffiInternalError: LocalizedError {
|
||||||
|
case bufferOverflow
|
||||||
|
case incompleteData
|
||||||
|
case unexpectedOptionalTag
|
||||||
|
case unexpectedEnumCase
|
||||||
|
case unexpectedNullPointer
|
||||||
|
case unexpectedRustCallStatusCode
|
||||||
|
case unexpectedRustCallError
|
||||||
|
case unexpectedStaleHandle
|
||||||
|
case rustPanic(_ message: String)
|
||||||
|
|
||||||
|
public var errorDescription: String? {
|
||||||
|
switch self {
|
||||||
|
case .bufferOverflow: return "Reading the requested value would read past the end of the buffer"
|
||||||
|
case .incompleteData: return "The buffer still has data after lifting its containing value"
|
||||||
|
case .unexpectedOptionalTag: return "Unexpected optional tag; should be 0 or 1"
|
||||||
|
case .unexpectedEnumCase: return "Raw enum value doesn't match any cases"
|
||||||
|
case .unexpectedNullPointer: return "Raw pointer value was null"
|
||||||
|
case .unexpectedRustCallStatusCode: return "Unexpected RustCallStatus code"
|
||||||
|
case .unexpectedRustCallError: return "CALL_ERROR but no errorClass specified"
|
||||||
|
case .unexpectedStaleHandle: return "The object in the handle map has been dropped already"
|
||||||
|
case let .rustPanic(message): return message
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fileprivate let CALL_SUCCESS: Int8 = 0
|
||||||
|
fileprivate let CALL_ERROR: Int8 = 1
|
||||||
|
fileprivate let CALL_PANIC: Int8 = 2
|
||||||
|
fileprivate let CALL_CANCELLED: Int8 = 3
|
||||||
|
|
||||||
|
fileprivate extension RustCallStatus {
|
||||||
|
init() {
|
||||||
|
self.init(
|
||||||
|
code: CALL_SUCCESS,
|
||||||
|
errorBuf: RustBuffer.init(
|
||||||
|
capacity: 0,
|
||||||
|
len: 0,
|
||||||
|
data: nil
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func rustCall<T>(_ callback: (UnsafeMutablePointer<RustCallStatus>) -> T) throws -> T {
|
||||||
|
try makeRustCall(callback, errorHandler: nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
private func rustCallWithError<T>(
|
||||||
|
_ errorHandler: @escaping (RustBuffer) throws -> Error,
|
||||||
|
_ callback: (UnsafeMutablePointer<RustCallStatus>) -> T) throws -> T {
|
||||||
|
try makeRustCall(callback, errorHandler: errorHandler)
|
||||||
|
}
|
||||||
|
|
||||||
|
private func makeRustCall<T>(
|
||||||
|
_ callback: (UnsafeMutablePointer<RustCallStatus>) -> T,
|
||||||
|
errorHandler: ((RustBuffer) throws -> Error)?
|
||||||
|
) throws -> T {
|
||||||
|
uniffiEnsureInitialized()
|
||||||
|
var callStatus = RustCallStatus.init()
|
||||||
|
let returnedVal = callback(&callStatus)
|
||||||
|
try uniffiCheckCallStatus(callStatus: callStatus, errorHandler: errorHandler)
|
||||||
|
return returnedVal
|
||||||
|
}
|
||||||
|
|
||||||
|
private func uniffiCheckCallStatus(
|
||||||
|
callStatus: RustCallStatus,
|
||||||
|
errorHandler: ((RustBuffer) throws -> Error)?
|
||||||
|
) throws {
|
||||||
|
switch callStatus.code {
|
||||||
|
case CALL_SUCCESS:
|
||||||
|
return
|
||||||
|
|
||||||
|
case CALL_ERROR:
|
||||||
|
if let errorHandler = errorHandler {
|
||||||
|
throw try errorHandler(callStatus.errorBuf)
|
||||||
|
} else {
|
||||||
|
callStatus.errorBuf.deallocate()
|
||||||
|
throw UniffiInternalError.unexpectedRustCallError
|
||||||
|
}
|
||||||
|
|
||||||
|
case CALL_PANIC:
|
||||||
|
// When the rust code sees a panic, it tries to construct a RustBuffer
|
||||||
|
// with the message. But if that code panics, then it just sends back
|
||||||
|
// an empty buffer.
|
||||||
|
if callStatus.errorBuf.len > 0 {
|
||||||
|
throw UniffiInternalError.rustPanic(try FfiConverterString.lift(callStatus.errorBuf))
|
||||||
|
} else {
|
||||||
|
callStatus.errorBuf.deallocate()
|
||||||
|
throw UniffiInternalError.rustPanic("Rust panic")
|
||||||
|
}
|
||||||
|
|
||||||
|
case CALL_CANCELLED:
|
||||||
|
throw CancellationError()
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw UniffiInternalError.unexpectedRustCallStatusCode
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Public interface members begin here.
|
||||||
|
|
||||||
|
|
||||||
|
fileprivate struct FfiConverterString: FfiConverter {
|
||||||
|
typealias SwiftType = String
|
||||||
|
typealias FfiType = RustBuffer
|
||||||
|
|
||||||
|
public static func lift(_ value: RustBuffer) throws -> String {
|
||||||
|
defer {
|
||||||
|
value.deallocate()
|
||||||
|
}
|
||||||
|
if value.data == nil {
|
||||||
|
return String()
|
||||||
|
}
|
||||||
|
let bytes = UnsafeBufferPointer<UInt8>(start: value.data!, count: Int(value.len))
|
||||||
|
return String(bytes: bytes, encoding: String.Encoding.utf8)!
|
||||||
|
}
|
||||||
|
|
||||||
|
public static func lower(_ value: String) -> RustBuffer {
|
||||||
|
return value.utf8CString.withUnsafeBufferPointer { ptr in
|
||||||
|
// The swift string gives us int8_t, we want uint8_t.
|
||||||
|
ptr.withMemoryRebound(to: UInt8.self) { ptr in
|
||||||
|
// The swift string gives us a trailing null byte, we don't want it.
|
||||||
|
let buf = UnsafeBufferPointer(rebasing: ptr.prefix(upTo: ptr.count - 1))
|
||||||
|
return RustBuffer.from(buf)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> String {
|
||||||
|
let len: Int32 = try readInt(&buf)
|
||||||
|
return String(bytes: try readBytes(&buf, count: Int(len)), encoding: String.Encoding.utf8)!
|
||||||
|
}
|
||||||
|
|
||||||
|
public static func write(_ value: String, into buf: inout [UInt8]) {
|
||||||
|
let len = Int32(value.utf8.count)
|
||||||
|
writeInt(&buf, len)
|
||||||
|
writeBytes(&buf, value.utf8)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fileprivate struct FfiConverterSequenceString: FfiConverterRustBuffer {
|
||||||
|
typealias SwiftType = [String]
|
||||||
|
|
||||||
|
public static func write(_ value: [String], into buf: inout [UInt8]) {
|
||||||
|
let len = Int32(value.count)
|
||||||
|
writeInt(&buf, len)
|
||||||
|
for item in value {
|
||||||
|
FfiConverterString.write(item, into: &buf)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> [String] {
|
||||||
|
let len: Int32 = try readInt(&buf)
|
||||||
|
var seq = [String]()
|
||||||
|
seq.reserveCapacity(Int(len))
|
||||||
|
for _ in 0 ..< len {
|
||||||
|
seq.append(try FfiConverterString.read(from: &buf))
|
||||||
|
}
|
||||||
|
return seq
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private let UNIFFI_RUST_FUTURE_POLL_READY: Int8 = 0
|
||||||
|
private let UNIFFI_RUST_FUTURE_POLL_MAYBE_READY: Int8 = 1
|
||||||
|
|
||||||
|
fileprivate func uniffiRustCallAsync<F, T>(
|
||||||
|
rustFutureFunc: () -> UnsafeMutableRawPointer,
|
||||||
|
pollFunc: (UnsafeMutableRawPointer, UnsafeMutableRawPointer) -> (),
|
||||||
|
completeFunc: (UnsafeMutableRawPointer, UnsafeMutablePointer<RustCallStatus>) -> F,
|
||||||
|
freeFunc: (UnsafeMutableRawPointer) -> (),
|
||||||
|
liftFunc: (F) throws -> T,
|
||||||
|
errorHandler: ((RustBuffer) throws -> Error)?
|
||||||
|
) async throws -> T {
|
||||||
|
// Make sure to call uniffiEnsureInitialized() since future creation doesn't have a
|
||||||
|
// RustCallStatus param, so doesn't use makeRustCall()
|
||||||
|
uniffiEnsureInitialized()
|
||||||
|
let rustFuture = rustFutureFunc()
|
||||||
|
defer {
|
||||||
|
freeFunc(rustFuture)
|
||||||
|
}
|
||||||
|
var pollResult: Int8;
|
||||||
|
repeat {
|
||||||
|
pollResult = await withUnsafeContinuation {
|
||||||
|
pollFunc(rustFuture, ContinuationHolder($0).toOpaque())
|
||||||
|
}
|
||||||
|
} while pollResult != UNIFFI_RUST_FUTURE_POLL_READY
|
||||||
|
|
||||||
|
return try liftFunc(makeRustCall(
|
||||||
|
{ completeFunc(rustFuture, $0) },
|
||||||
|
errorHandler: errorHandler
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Callback handlers for an async calls. These are invoked by Rust when the future is ready. They
|
||||||
|
// lift the return value or error and resume the suspended function.
|
||||||
|
fileprivate func uniffiFutureContinuationCallback(ptr: UnsafeMutableRawPointer, pollResult: Int8) {
|
||||||
|
ContinuationHolder.fromOpaque(ptr).resume(pollResult)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wraps UnsafeContinuation in a class so that we can use reference counting when passing it across
|
||||||
|
// the FFI
|
||||||
|
fileprivate class ContinuationHolder {
|
||||||
|
let continuation: UnsafeContinuation<Int8, Never>
|
||||||
|
|
||||||
|
init(_ continuation: UnsafeContinuation<Int8, Never>) {
|
||||||
|
self.continuation = continuation
|
||||||
|
}
|
||||||
|
|
||||||
|
func resume(_ pollResult: Int8) {
|
||||||
|
self.continuation.resume(returning: pollResult)
|
||||||
|
}
|
||||||
|
|
||||||
|
func toOpaque() -> UnsafeMutableRawPointer {
|
||||||
|
return Unmanaged<ContinuationHolder>.passRetained(self).toOpaque()
|
||||||
|
}
|
||||||
|
|
||||||
|
static func fromOpaque(_ ptr: UnsafeRawPointer) -> ContinuationHolder {
|
||||||
|
return Unmanaged<ContinuationHolder>.fromOpaque(ptr).takeRetainedValue()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fileprivate func uniffiInitContinuationCallback() {
|
||||||
|
ffi_mobile_rust_future_continuation_callback_set(uniffiFutureContinuationCallback)
|
||||||
|
}
|
||||||
|
|
||||||
|
public func auth(url: String, secretKey: String) async -> [String] {
|
||||||
|
return try! await uniffiRustCallAsync(
|
||||||
|
rustFutureFunc: {
|
||||||
|
uniffi_mobile_fn_func_auth(
|
||||||
|
FfiConverterString.lower(url),
|
||||||
|
FfiConverterString.lower(secretKey)
|
||||||
|
)
|
||||||
|
},
|
||||||
|
pollFunc: ffi_mobile_rust_future_poll_rust_buffer,
|
||||||
|
completeFunc: ffi_mobile_rust_future_complete_rust_buffer,
|
||||||
|
freeFunc: ffi_mobile_rust_future_free_rust_buffer,
|
||||||
|
liftFunc: FfiConverterSequenceString.lift,
|
||||||
|
errorHandler: nil
|
||||||
|
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public func myexample() -> [String] {
|
||||||
|
return try! FfiConverterSequenceString.lift(
|
||||||
|
try! rustCall() {
|
||||||
|
uniffi_mobile_fn_func_myexample($0)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private enum InitializationResult {
|
||||||
|
case ok
|
||||||
|
case contractVersionMismatch
|
||||||
|
case apiChecksumMismatch
|
||||||
|
}
|
||||||
|
// Use a global variables to perform the versioning checks. Swift ensures that
|
||||||
|
// the code inside is only computed once.
|
||||||
|
private var initializationResult: InitializationResult {
|
||||||
|
// Get the bindings contract version from our ComponentInterface
|
||||||
|
let bindings_contract_version = 24
|
||||||
|
// Get the scaffolding contract version by calling the into the dylib
|
||||||
|
let scaffolding_contract_version = ffi_mobile_uniffi_contract_version()
|
||||||
|
if bindings_contract_version != scaffolding_contract_version {
|
||||||
|
return InitializationResult.contractVersionMismatch
|
||||||
|
}
|
||||||
|
if (uniffi_mobile_checksum_func_auth() != 55720) {
|
||||||
|
return InitializationResult.apiChecksumMismatch
|
||||||
|
}
|
||||||
|
if (uniffi_mobile_checksum_func_myexample() != 65225) {
|
||||||
|
return InitializationResult.apiChecksumMismatch
|
||||||
|
}
|
||||||
|
|
||||||
|
uniffiInitContinuationCallback()
|
||||||
|
return InitializationResult.ok
|
||||||
|
}
|
||||||
|
|
||||||
|
private func uniffiEnsureInitialized() {
|
||||||
|
switch initializationResult {
|
||||||
|
case .ok:
|
||||||
|
break
|
||||||
|
case .contractVersionMismatch:
|
||||||
|
fatalError("UniFFI contract version mismatch: try cleaning and rebuilding your project")
|
||||||
|
case .apiChecksumMismatch:
|
||||||
|
fatalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project")
|
||||||
|
}
|
||||||
|
}
|
||||||
194
rust/bindings/mobileFFI.h
Normal file
@@ -0,0 +1,194 @@
|
|||||||
|
// This file was autogenerated by some hot garbage in the `uniffi` crate.
|
||||||
|
// Trust me, you don't want to mess with it!
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
// The following structs are used to implement the lowest level
|
||||||
|
// of the FFI, and thus useful to multiple uniffied crates.
|
||||||
|
// We ensure they are declared exactly once, with a header guard, UNIFFI_SHARED_H.
|
||||||
|
#ifdef UNIFFI_SHARED_H
|
||||||
|
// We also try to prevent mixing versions of shared uniffi header structs.
|
||||||
|
// If you add anything to the #else block, you must increment the version suffix in UNIFFI_SHARED_HEADER_V4
|
||||||
|
#ifndef UNIFFI_SHARED_HEADER_V4
|
||||||
|
#error Combining helper code from multiple versions of uniffi is not supported
|
||||||
|
#endif // ndef UNIFFI_SHARED_HEADER_V4
|
||||||
|
#else
|
||||||
|
#define UNIFFI_SHARED_H
|
||||||
|
#define UNIFFI_SHARED_HEADER_V4
|
||||||
|
// ⚠️ Attention: If you change this #else block (ending in `#endif // def UNIFFI_SHARED_H`) you *must* ⚠️
|
||||||
|
// ⚠️ increment the version suffix in all instances of UNIFFI_SHARED_HEADER_V4 in this file. ⚠️
|
||||||
|
|
||||||
|
typedef struct RustBuffer
|
||||||
|
{
|
||||||
|
int32_t capacity;
|
||||||
|
int32_t len;
|
||||||
|
uint8_t *_Nullable data;
|
||||||
|
} RustBuffer;
|
||||||
|
|
||||||
|
typedef int32_t (*ForeignCallback)(uint64_t, int32_t, const uint8_t *_Nonnull, int32_t, RustBuffer *_Nonnull);
|
||||||
|
|
||||||
|
// Task defined in Rust that Swift executes
|
||||||
|
typedef void (*UniFfiRustTaskCallback)(const void * _Nullable, int8_t);
|
||||||
|
|
||||||
|
// Callback to execute Rust tasks using a Swift Task
|
||||||
|
//
|
||||||
|
// Args:
|
||||||
|
// executor: ForeignExecutor lowered into a size_t value
|
||||||
|
// delay: Delay in MS
|
||||||
|
// task: UniFfiRustTaskCallback to call
|
||||||
|
// task_data: data to pass the task callback
|
||||||
|
typedef int8_t (*UniFfiForeignExecutorCallback)(size_t, uint32_t, UniFfiRustTaskCallback _Nullable, const void * _Nullable);
|
||||||
|
|
||||||
|
typedef struct ForeignBytes
|
||||||
|
{
|
||||||
|
int32_t len;
|
||||||
|
const uint8_t *_Nullable data;
|
||||||
|
} ForeignBytes;
|
||||||
|
|
||||||
|
// Error definitions
|
||||||
|
typedef struct RustCallStatus {
|
||||||
|
int8_t code;
|
||||||
|
RustBuffer errorBuf;
|
||||||
|
} RustCallStatus;
|
||||||
|
|
||||||
|
// ⚠️ Attention: If you change this #else block (ending in `#endif // def UNIFFI_SHARED_H`) you *must* ⚠️
|
||||||
|
// ⚠️ increment the version suffix in all instances of UNIFFI_SHARED_HEADER_V4 in this file. ⚠️
|
||||||
|
#endif // def UNIFFI_SHARED_H
|
||||||
|
|
||||||
|
// Continuation callback for UniFFI Futures
|
||||||
|
typedef void (*UniFfiRustFutureContinuation)(void * _Nonnull, int8_t);
|
||||||
|
|
||||||
|
// Scaffolding functions
|
||||||
|
void* _Nonnull uniffi_mobile_fn_func_auth(RustBuffer url, RustBuffer secret_key
|
||||||
|
);
|
||||||
|
RustBuffer uniffi_mobile_fn_func_myexample(RustCallStatus *_Nonnull out_status
|
||||||
|
|
||||||
|
);
|
||||||
|
RustBuffer ffi_mobile_rustbuffer_alloc(int32_t size, RustCallStatus *_Nonnull out_status
|
||||||
|
);
|
||||||
|
RustBuffer ffi_mobile_rustbuffer_from_bytes(ForeignBytes bytes, RustCallStatus *_Nonnull out_status
|
||||||
|
);
|
||||||
|
void ffi_mobile_rustbuffer_free(RustBuffer buf, RustCallStatus *_Nonnull out_status
|
||||||
|
);
|
||||||
|
RustBuffer ffi_mobile_rustbuffer_reserve(RustBuffer buf, int32_t additional, RustCallStatus *_Nonnull out_status
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_continuation_callback_set(UniFfiRustFutureContinuation _Nonnull callback
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_poll_u8(void* _Nonnull handle, void* _Nonnull uniffi_callback
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_cancel_u8(void* _Nonnull handle
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_free_u8(void* _Nonnull handle
|
||||||
|
);
|
||||||
|
uint8_t ffi_mobile_rust_future_complete_u8(void* _Nonnull handle, RustCallStatus *_Nonnull out_status
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_poll_i8(void* _Nonnull handle, void* _Nonnull uniffi_callback
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_cancel_i8(void* _Nonnull handle
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_free_i8(void* _Nonnull handle
|
||||||
|
);
|
||||||
|
int8_t ffi_mobile_rust_future_complete_i8(void* _Nonnull handle, RustCallStatus *_Nonnull out_status
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_poll_u16(void* _Nonnull handle, void* _Nonnull uniffi_callback
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_cancel_u16(void* _Nonnull handle
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_free_u16(void* _Nonnull handle
|
||||||
|
);
|
||||||
|
uint16_t ffi_mobile_rust_future_complete_u16(void* _Nonnull handle, RustCallStatus *_Nonnull out_status
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_poll_i16(void* _Nonnull handle, void* _Nonnull uniffi_callback
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_cancel_i16(void* _Nonnull handle
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_free_i16(void* _Nonnull handle
|
||||||
|
);
|
||||||
|
int16_t ffi_mobile_rust_future_complete_i16(void* _Nonnull handle, RustCallStatus *_Nonnull out_status
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_poll_u32(void* _Nonnull handle, void* _Nonnull uniffi_callback
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_cancel_u32(void* _Nonnull handle
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_free_u32(void* _Nonnull handle
|
||||||
|
);
|
||||||
|
uint32_t ffi_mobile_rust_future_complete_u32(void* _Nonnull handle, RustCallStatus *_Nonnull out_status
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_poll_i32(void* _Nonnull handle, void* _Nonnull uniffi_callback
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_cancel_i32(void* _Nonnull handle
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_free_i32(void* _Nonnull handle
|
||||||
|
);
|
||||||
|
int32_t ffi_mobile_rust_future_complete_i32(void* _Nonnull handle, RustCallStatus *_Nonnull out_status
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_poll_u64(void* _Nonnull handle, void* _Nonnull uniffi_callback
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_cancel_u64(void* _Nonnull handle
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_free_u64(void* _Nonnull handle
|
||||||
|
);
|
||||||
|
uint64_t ffi_mobile_rust_future_complete_u64(void* _Nonnull handle, RustCallStatus *_Nonnull out_status
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_poll_i64(void* _Nonnull handle, void* _Nonnull uniffi_callback
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_cancel_i64(void* _Nonnull handle
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_free_i64(void* _Nonnull handle
|
||||||
|
);
|
||||||
|
int64_t ffi_mobile_rust_future_complete_i64(void* _Nonnull handle, RustCallStatus *_Nonnull out_status
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_poll_f32(void* _Nonnull handle, void* _Nonnull uniffi_callback
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_cancel_f32(void* _Nonnull handle
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_free_f32(void* _Nonnull handle
|
||||||
|
);
|
||||||
|
float ffi_mobile_rust_future_complete_f32(void* _Nonnull handle, RustCallStatus *_Nonnull out_status
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_poll_f64(void* _Nonnull handle, void* _Nonnull uniffi_callback
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_cancel_f64(void* _Nonnull handle
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_free_f64(void* _Nonnull handle
|
||||||
|
);
|
||||||
|
double ffi_mobile_rust_future_complete_f64(void* _Nonnull handle, RustCallStatus *_Nonnull out_status
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_poll_pointer(void* _Nonnull handle, void* _Nonnull uniffi_callback
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_cancel_pointer(void* _Nonnull handle
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_free_pointer(void* _Nonnull handle
|
||||||
|
);
|
||||||
|
void*_Nonnull ffi_mobile_rust_future_complete_pointer(void* _Nonnull handle, RustCallStatus *_Nonnull out_status
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_poll_rust_buffer(void* _Nonnull handle, void* _Nonnull uniffi_callback
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_cancel_rust_buffer(void* _Nonnull handle
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_free_rust_buffer(void* _Nonnull handle
|
||||||
|
);
|
||||||
|
RustBuffer ffi_mobile_rust_future_complete_rust_buffer(void* _Nonnull handle, RustCallStatus *_Nonnull out_status
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_poll_void(void* _Nonnull handle, void* _Nonnull uniffi_callback
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_cancel_void(void* _Nonnull handle
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_free_void(void* _Nonnull handle
|
||||||
|
);
|
||||||
|
void ffi_mobile_rust_future_complete_void(void* _Nonnull handle, RustCallStatus *_Nonnull out_status
|
||||||
|
);
|
||||||
|
uint16_t uniffi_mobile_checksum_func_auth(void
|
||||||
|
|
||||||
|
);
|
||||||
|
uint16_t uniffi_mobile_checksum_func_myexample(void
|
||||||
|
|
||||||
|
);
|
||||||
|
uint32_t ffi_mobile_uniffi_contract_version(void
|
||||||
|
|
||||||
|
);
|
||||||
|
|
||||||