diff --git a/.github/workflows/mobile-sdk-artifacts.yml b/.github/workflows/mobile-sdk-artifacts.yml new file mode 100644 index 00000000..ac18ed01 --- /dev/null +++ b/.github/workflows/mobile-sdk-artifacts.yml @@ -0,0 +1,75 @@ +name: Mobile SDK Artifacts + +on: + workflow_dispatch: + release: + types: [published] + +jobs: + package-mobile-sdk: + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, macos-latest] + runs-on: ${{ matrix.os }} + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable + - name: Build and package mobile SDK artifact + run: ./scripts/package-mobile-sdk.sh + - name: Upload mobile SDK artifact + uses: actions/upload-artifact@v4 + with: + name: mobile-sdk-${{ matrix.os }} + path: | + dist/mobile-sdk/*.tar.gz + dist/mobile-sdk/*.tar.gz.sha256 + + package-rust-ffi: + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, macos-latest] + runs-on: ${{ matrix.os }} + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable + - name: Build and package Rust FFI artifact + run: ./scripts/package-rust-ffi-dylib.sh + - name: Upload Rust FFI artifact + uses: actions/upload-artifact@v4 + with: + name: rust-ffi-${{ matrix.os }} + path: | + dist/rust-ffi/*.tar.gz + dist/rust-ffi/*.tar.gz.sha256 + + publish-release-assets: + if: github.event_name == 'release' + needs: [package-mobile-sdk, package-rust-ffi] + runs-on: ubuntu-latest + permissions: + contents: write + steps: + - name: Download mobile SDK artifacts + uses: actions/download-artifact@v4 + with: + pattern: mobile-sdk-* + merge-multiple: true + path: dist/mobile-sdk + + - name: Download Rust FFI artifacts + uses: actions/download-artifact@v4 + with: + pattern: rust-ffi-* + merge-multiple: true + path: dist/rust-ffi + + - name: Publish artifacts to release + uses: softprops/action-gh-release@v2 + with: + files: | + dist/mobile-sdk/*.tar.gz + dist/mobile-sdk/*.tar.gz.sha256 + dist/rust-ffi/*.tar.gz + dist/rust-ffi/*.tar.gz.sha256 diff --git a/AGENTS.md b/AGENTS.md index 3e157aaf..6baea0a1 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -164,6 +164,19 @@ cargo check --workspace cargo test --workspace ``` +### Mobile SDK Bindings (`sdk/`) — landed on `develop` (Slice 3) + +UniFFI-generated iOS (Swift) and Android (Kotlin) bindings over `core/mobile-sdk`, plus sample consumers and packaging scripts. The `sdk/*/generated/**` files are machine-generated — **regenerate, never hand-edit** (`scripts/generate-mobile-sdk-bindings.sh`; output is byte-reproducible from the crate). + +| File | Purpose | +|------|---------| +| `sdk/ios/generated/*` | UniFFI Swift bindings + FFI header/modulemap for iOS consumers. | +| `sdk/android/generated/.../skilly_core_mobile_sdk.kt` | UniFFI Kotlin bindings for Android consumers. | +| `sdk/{ios,android}/sample/*` | Sample apps showing policy gating + realtime replay against the bindings. | +| `scripts/generate-mobile-sdk-bindings.sh` | Builds the crate + regenerates Swift/Kotlin bindings into `sdk/`. | +| `scripts/package-mobile-sdk.sh` / `validate-mobile-sdk-consumers.sh` | Package and end-to-end validate generated SDK consumers. | +| `.github/workflows/mobile-sdk-artifacts.yml` | Release-triggered packaging/publishing of mobile SDK + FFI tarballs. | + ### Skill Files The repo ships 5 bundled skills under `skills/`, also copied into the app bundle under `Resources/skills/` so new users get them without downloading anything. diff --git a/docs/architecture/mobile-sdk-phase-validation-report.md b/docs/architecture/mobile-sdk-phase-validation-report.md new file mode 100644 index 00000000..2405563e --- /dev/null +++ b/docs/architecture/mobile-sdk-phase-validation-report.md @@ -0,0 +1,44 @@ +# Mobile SDK Phase Validation Report + +Date: 2026-04-18 +Branch: `feature/skills-bridge-swift` + +## Scope +Validation for roadmap Phase 6 (Mobile SDK Surface) artifacts: +1. UniFFI-exported mobile Rust crate. +2. Workspace compilation and tests including mobile SDK crate. +3. Swift/Kotlin binding generation from compiled library. +4. Sample integration snippets aligned with generated API. +5. Runtime validation for generated Swift/Kotlin sample consumers. +6. Package/distribution automation for SDK artifacts. + +## Commands Executed +```bash +cargo check --workspace +cargo test --workspace +./scripts/generate-mobile-sdk-bindings.sh +./scripts/validate-mobile-sdk-consumers.sh +./scripts/package-mobile-sdk.sh +``` + +## Results +- `cargo check --workspace`: pass +- `cargo test --workspace`: pass + - includes mobile SDK crate tests (`skilly-core-mobile-sdk`): 3 passed +- `./scripts/generate-mobile-sdk-bindings.sh`: pass + - generated `sdk/ios/generated/skilly_core_mobile_sdk.swift` + - generated `sdk/android/generated/uniffi/skilly_core_mobile_sdk/skilly_core_mobile_sdk.kt` +- `./scripts/validate-mobile-sdk-consumers.sh`: pass + - Kotlin/JVM sample runtime executed against generated Kotlin bindings + - Swift sample runtime executed against generated Swift bindings (macOS host) +- `./scripts/package-mobile-sdk.sh`: pass + - generated distributable artifact in `dist/mobile-sdk/` with checksum + +## Key Outcomes +1. Phase 6 core requirement is implemented via `core/mobile-sdk` UniFFI API surface. +2. Swift and Kotlin bindings are generated from source with a single script command. +3. iOS and Android sample usage snippets are present under `sdk/ios/sample` and `sdk/android/sample`. +4. Release automation is in place via `.github/workflows/mobile-sdk-artifacts.yml` for packaging and publishing SDK artifacts. + +## Remaining Work +1. Full runtime validation inside real iOS and Android host apps (simulator/device lanes). diff --git a/scripts/generate-mobile-sdk-bindings.sh b/scripts/generate-mobile-sdk-bindings.sh new file mode 100755 index 00000000..015c77d3 --- /dev/null +++ b/scripts/generate-mobile-sdk-bindings.sh @@ -0,0 +1,50 @@ +#!/usr/bin/env bash +set -euo pipefail + +REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +cd "$REPO_ROOT" + +LIB_NAME="skilly_core_mobile_sdk" +BUILD_PROFILE="debug" +IOS_OUTPUT_DIR="$REPO_ROOT/sdk/ios/generated" +ANDROID_OUTPUT_DIR="$REPO_ROOT/sdk/android/generated" + +cargo build -p skilly-core-mobile-sdk + +case "$(uname -s)" in + Darwin) + LIB_PATH="$REPO_ROOT/target/$BUILD_PROFILE/lib${LIB_NAME}.dylib" + ;; + Linux) + LIB_PATH="$REPO_ROOT/target/$BUILD_PROFILE/lib${LIB_NAME}.so" + ;; + MINGW*|MSYS*|CYGWIN*) + LIB_PATH="$REPO_ROOT/target/$BUILD_PROFILE/${LIB_NAME}.dll" + ;; + *) + echo "Unsupported host OS for binding generation." >&2 + exit 1 + ;; +esac + +if [[ ! -f "$LIB_PATH" ]]; then + echo "Expected compiled library at $LIB_PATH" >&2 + exit 1 +fi + +mkdir -p "$IOS_OUTPUT_DIR" "$ANDROID_OUTPUT_DIR" + +cargo run -p skilly-core-mobile-sdk --bin uniffi-bindgen -- \ + generate \ + --library "$LIB_PATH" \ + --language swift \ + --out-dir "$IOS_OUTPUT_DIR" + +cargo run -p skilly-core-mobile-sdk --bin uniffi-bindgen -- \ + generate \ + --library "$LIB_PATH" \ + --language kotlin \ + --out-dir "$ANDROID_OUTPUT_DIR" + +echo "Generated Swift bindings in $IOS_OUTPUT_DIR" +echo "Generated Kotlin bindings in $ANDROID_OUTPUT_DIR" diff --git a/scripts/package-mobile-sdk.sh b/scripts/package-mobile-sdk.sh new file mode 100755 index 00000000..5270ef22 --- /dev/null +++ b/scripts/package-mobile-sdk.sh @@ -0,0 +1,78 @@ +#!/usr/bin/env bash +set -euo pipefail + +REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +cd "$REPO_ROOT" + +MOBILE_SDK_CRATE_PATH="$REPO_ROOT/core/mobile-sdk/Cargo.toml" +MOBILE_SDK_VERSION="$(sed -n 's/^version = "\([0-9.]*\)"/\1/p' "$MOBILE_SDK_CRATE_PATH" | head -1)" +if [[ -z "$MOBILE_SDK_VERSION" ]]; then + echo "Could not determine mobile SDK version from $MOBILE_SDK_CRATE_PATH" >&2 + exit 1 +fi + +RELEASE_LIBRARY_DIR="$REPO_ROOT/target/release" +DIST_ROOT="$REPO_ROOT/dist/mobile-sdk" +DIST_VERSION_DIR="$DIST_ROOT/v${MOBILE_SDK_VERSION}" +DIST_PLATFORM_NAME="$(uname -s | tr '[:upper:]' '[:lower:]')" +DIST_OUTPUT_FILE="$DIST_ROOT/skilly-mobile-sdk-v${MOBILE_SDK_VERSION}-${DIST_PLATFORM_NAME}.tar.gz" + +rm -rf "$DIST_VERSION_DIR" +mkdir -p \ + "$DIST_VERSION_DIR/ios/generated" \ + "$DIST_VERSION_DIR/ios/sample" \ + "$DIST_VERSION_DIR/android/generated" \ + "$DIST_VERSION_DIR/android/sample" \ + "$DIST_VERSION_DIR/native" + +./scripts/generate-mobile-sdk-bindings.sh +cargo build -p skilly-core-mobile-sdk --release + +case "$(uname -s)" in + Darwin) + RELEASE_LIBRARY_PATH="$RELEASE_LIBRARY_DIR/libskilly_core_mobile_sdk.dylib" + ;; + Linux) + RELEASE_LIBRARY_PATH="$RELEASE_LIBRARY_DIR/libskilly_core_mobile_sdk.so" + ;; + MINGW*|MSYS*|CYGWIN*) + RELEASE_LIBRARY_PATH="$RELEASE_LIBRARY_DIR/skilly_core_mobile_sdk.dll" + ;; + *) + echo "Unsupported host OS for packaging." >&2 + exit 1 + ;; +esac + +if [[ ! -f "$RELEASE_LIBRARY_PATH" ]]; then + echo "Expected release library at $RELEASE_LIBRARY_PATH" >&2 + exit 1 +fi + +cp -R sdk/ios/generated/. "$DIST_VERSION_DIR/ios/generated/" +cp -R sdk/ios/sample/. "$DIST_VERSION_DIR/ios/sample/" +cp -R sdk/android/generated/. "$DIST_VERSION_DIR/android/generated/" +cp -R sdk/android/sample/. "$DIST_VERSION_DIR/android/sample/" +cp "$RELEASE_LIBRARY_PATH" "$DIST_VERSION_DIR/native/" +cp sdk/README.md "$DIST_VERSION_DIR/README.md" + +cat > "$DIST_VERSION_DIR/MANIFEST.txt" </dev/null 2>&1; then + shasum -a 256 "$DIST_OUTPUT_FILE" > "${DIST_OUTPUT_FILE}.sha256" +elif command -v sha256sum >/dev/null 2>&1; then + sha256sum "$DIST_OUTPUT_FILE" > "${DIST_OUTPUT_FILE}.sha256" +fi + +echo "Packaged mobile SDK artifact: $DIST_OUTPUT_FILE" +if [[ -f "${DIST_OUTPUT_FILE}.sha256" ]]; then + echo "Checksum file: ${DIST_OUTPUT_FILE}.sha256" +fi diff --git a/scripts/validate-mobile-sdk-consumers.sh b/scripts/validate-mobile-sdk-consumers.sh new file mode 100755 index 00000000..5bbdaf8b --- /dev/null +++ b/scripts/validate-mobile-sdk-consumers.sh @@ -0,0 +1,92 @@ +#!/usr/bin/env bash +set -euo pipefail + +REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +cd "$REPO_ROOT" + +BUILD_DIR="$REPO_ROOT/build/mobile-sdk-validation" +KOTLIN_VERSION="2.0.21" +KOTLIN_DISTRIBUTION_URL="https://github.com/JetBrains/kotlin/releases/download/v${KOTLIN_VERSION}/kotlin-compiler-${KOTLIN_VERSION}.zip" +JNA_VERSION="5.17.0" +JNA_JAR_PATH="$BUILD_DIR/jna-${JNA_VERSION}.jar" +KOTLIN_MAIN_PATH="$BUILD_DIR/SkillyMobileSdkValidationMain.kt" +KOTLIN_OUTPUT_JAR="$BUILD_DIR/skilly-mobile-sdk-validation.jar" +SWIFT_MAIN_PATH="$BUILD_DIR/SkillyMobileSdkValidationMain.swift" +SWIFT_BINARY_PATH="$BUILD_DIR/skilly-mobile-sdk-validation" +KOTLIN_COMPILER_ROOT="$BUILD_DIR/kotlin-compiler" + +mkdir -p "$BUILD_DIR" + +./scripts/generate-mobile-sdk-bindings.sh + +cargo build -p skilly-core-mobile-sdk + +if [[ ! -f "$JNA_JAR_PATH" ]]; then + curl -L -o "$JNA_JAR_PATH" "https://repo1.maven.org/maven2/net/java/dev/jna/jna/${JNA_VERSION}/jna-${JNA_VERSION}.jar" +fi + +KOTLIN_COMPILER_BIN="$(command -v kotlinc || true)" +if [[ -z "$KOTLIN_COMPILER_BIN" ]]; then + KOTLIN_COMPILER_BIN="$KOTLIN_COMPILER_ROOT/kotlinc/bin/kotlinc" + if [[ ! -x "$KOTLIN_COMPILER_BIN" ]]; then + KOTLIN_ZIP_PATH="$BUILD_DIR/kotlin-compiler-${KOTLIN_VERSION}.zip" + if [[ ! -f "$KOTLIN_ZIP_PATH" ]]; then + curl -L -o "$KOTLIN_ZIP_PATH" "$KOTLIN_DISTRIBUTION_URL" + fi + + rm -rf "$KOTLIN_COMPILER_ROOT" + mkdir -p "$KOTLIN_COMPILER_ROOT" + unzip -q "$KOTLIN_ZIP_PATH" -d "$KOTLIN_COMPILER_ROOT" + fi +fi + +cat > "$KOTLIN_MAIN_PATH" <<'KOTLIN' +import app.tryskilly.sdk.PolicyAndRealtimeExample + +fun main() { + PolicyAndRealtimeExample.runDemo() +} +KOTLIN + +"$KOTLIN_COMPILER_BIN" \ + sdk/android/generated/uniffi/skilly_core_mobile_sdk/skilly_core_mobile_sdk.kt \ + sdk/android/sample/src/main/kotlin/app/tryskilly/sdk/PolicyAndRealtimeExample.kt \ + "$KOTLIN_MAIN_PATH" \ + -cp "$JNA_JAR_PATH" \ + -include-runtime \ + -d "$KOTLIN_OUTPUT_JAR" + +java \ + -Djna.library.path="$REPO_ROOT/target/debug" \ + -Djava.library.path="$REPO_ROOT/target/debug" \ + -cp "$KOTLIN_OUTPUT_JAR:$JNA_JAR_PATH" \ + SkillyMobileSdkValidationMainKt + +if [[ "$(uname -s)" == "Darwin" ]]; then + cat > "$SWIFT_MAIN_PATH" <<'SWIFT' +import Foundation + +@main +struct Main { + static func main() { + runPolicyAndRealtimeDemo() + } +} +SWIFT + + swiftc \ + sdk/ios/generated/skilly_core_mobile_sdk.swift \ + sdk/ios/sample/PolicyAndRealtimeExample.swift \ + "$SWIFT_MAIN_PATH" \ + -I sdk/ios/generated \ + -Xcc -fmodule-map-file="$REPO_ROOT/sdk/ios/generated/skilly_core_mobile_sdkFFI.modulemap" \ + -L "$REPO_ROOT/target/debug" \ + -lskilly_core_mobile_sdk \ + -o "$SWIFT_BINARY_PATH" + + DYLD_LIBRARY_PATH="$REPO_ROOT/target/debug" "$SWIFT_BINARY_PATH" +else + echo "Skipping Swift mobile SDK consumer runtime validation on non-macOS host." +fi + +echo "Mobile SDK consumer validation completed successfully." diff --git a/sdk/README.md b/sdk/README.md new file mode 100644 index 00000000..e9a3e1fa --- /dev/null +++ b/sdk/README.md @@ -0,0 +1,36 @@ +# Skilly Mobile SDK + +This directory contains generated mobile bindings and sample integrations for the shared Rust core. + +## Generate Bindings + +From repo root: + +```bash +./scripts/generate-mobile-sdk-bindings.sh +``` + +## Validate Consumer Runtime + +```bash +./scripts/validate-mobile-sdk-consumers.sh +``` + +## Build Distribution Artifacts + +```bash +./scripts/package-mobile-sdk.sh +``` + +Outputs: +- `sdk/ios/generated/` +- `sdk/android/generated/` + +The generated API currently exposes: +- policy gating (`can_start_turn_for_mobile`, trial/cap checks) +- realtime replay summaries (`replay_realtime_events_for_mobile`, `replay_realtime_events_from_json_for_mobile`) + +## Samples + +- `sdk/ios/sample/PolicyAndRealtimeExample.swift` +- `sdk/android/sample/src/main/kotlin/app/tryskilly/sdk/PolicyAndRealtimeExample.kt` diff --git a/sdk/android/README.md b/sdk/android/README.md new file mode 100644 index 00000000..04f31665 --- /dev/null +++ b/sdk/android/README.md @@ -0,0 +1,10 @@ +# Android SDK Artifacts + +- `generated/`: Kotlin bindings generated by UniFFI. +- `sample/`: sample Kotlin usage of generated APIs. + +## Regenerate + +```bash +./scripts/generate-mobile-sdk-bindings.sh +``` diff --git a/sdk/android/generated/uniffi/skilly_core_mobile_sdk/skilly_core_mobile_sdk.kt b/sdk/android/generated/uniffi/skilly_core_mobile_sdk/skilly_core_mobile_sdk.kt new file mode 100644 index 00000000..800c1d6e --- /dev/null +++ b/sdk/android/generated/uniffi/skilly_core_mobile_sdk/skilly_core_mobile_sdk.kt @@ -0,0 +1,1498 @@ +// 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.skilly_core_mobile_sdk + +// 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.atomic.AtomicLong +import java.util.concurrent.ConcurrentHashMap + +// 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. + +/** + * @suppress + */ +@Structure.FieldOrder("capacity", "len", "data") +open class RustBuffer : Structure() { + // Note: `capacity` and `len` are actually `ULong` values, but JVM only supports signed values. + // When dealing with these fields, make sure to call `toULong()`. + @JvmField var capacity: Long = 0 + @JvmField var len: Long = 0 + @JvmField var data: Pointer? = null + + class ByValue: RustBuffer(), Structure.ByValue + class ByReference: RustBuffer(), Structure.ByReference + + internal fun setValue(other: RustBuffer) { + capacity = other.capacity + len = other.len + data = other.data + } + + companion object { + internal fun alloc(size: ULong = 0UL) = uniffiRustCall() { status -> + // Note: need to convert the size to a `Long` value to make this work with JVM. + UniffiLib.INSTANCE.ffi_skilly_core_mobile_sdk_rustbuffer_alloc(size.toLong(), status) + }.also { + if(it.data == null) { + throw RuntimeException("RustBuffer.alloc() returned null data pointer (size=${size})") + } + } + + internal fun create(capacity: ULong, len: ULong, data: Pointer?): RustBuffer.ByValue { + var buf = RustBuffer.ByValue() + buf.capacity = capacity.toLong() + buf.len = len.toLong() + buf.data = data + return buf + } + + internal fun free(buf: RustBuffer.ByValue) = uniffiRustCall() { status -> + UniffiLib.INSTANCE.ffi_skilly_core_mobile_sdk_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. + * + * @suppress + */ +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.setLong(0, value.capacity) + pointer.setLong(8, value.len) + pointer.setPointer(16, value.data) + } + + /** + * Get a `RustBuffer.ByValue` from this reference. + */ + fun getValue(): RustBuffer.ByValue { + val pointer = getPointer() + val value = RustBuffer.ByValue() + value.writeField("capacity", pointer.getLong(0)) + value.writeField("len", pointer.getLong(8)) + value.writeField("data", pointer.getLong(16)) + + 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") +internal 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. + * + * @suppress + */ +public interface FfiConverter { + // 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): ULong + + // 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).also { + it.order(ByteOrder.BIG_ENDIAN) + } + write(value, bbuf) + rbuf.writeField("len", bbuf.position().toLong()) + 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 + * + * @suppress + */ +public interface FfiConverterRustBuffer: FfiConverter { + 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. + +internal const val UNIFFI_CALL_SUCCESS = 0.toByte() +internal const val UNIFFI_CALL_ERROR = 1.toByte() +internal const val UNIFFI_CALL_UNEXPECTED_ERROR = 2.toByte() + +@Structure.FieldOrder("code", "error_buf") +internal open class UniffiRustCallStatus : Structure() { + @JvmField var code: Byte = 0 + @JvmField var error_buf: RustBuffer.ByValue = RustBuffer.ByValue() + + class ByValue: UniffiRustCallStatus(), Structure.ByValue + + fun isSuccess(): Boolean { + return code == UNIFFI_CALL_SUCCESS + } + + fun isError(): Boolean { + return code == UNIFFI_CALL_ERROR + } + + fun isPanic(): Boolean { + return code == UNIFFI_CALL_UNEXPECTED_ERROR + } + + companion object { + fun create(code: Byte, errorBuf: RustBuffer.ByValue): UniffiRustCallStatus.ByValue { + val callStatus = UniffiRustCallStatus.ByValue() + callStatus.code = code + callStatus.error_buf = errorBuf + return callStatus + } + } +} + +class InternalException(message: String) : kotlin.Exception(message) + +/** + * Each top-level error class has a companion object that can lift the error from the call status's rust buffer + * + * @suppress + */ +interface UniffiRustCallStatusErrorHandler { + 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 uniffiRustCallWithError(errorHandler: UniffiRustCallStatusErrorHandler, callback: (UniffiRustCallStatus) -> U): U { + var status = UniffiRustCallStatus() + val return_value = callback(status) + uniffiCheckCallStatus(errorHandler, status) + return return_value +} + +// Check UniffiRustCallStatus and throw an error if the call wasn't successful +private fun uniffiCheckCallStatus(errorHandler: UniffiRustCallStatusErrorHandler, status: UniffiRustCallStatus) { + 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") + } +} + +/** + * UniffiRustCallStatusErrorHandler implementation for times when we don't expect a CALL_ERROR + * + * @suppress + */ +object UniffiNullRustCallStatusErrorHandler: UniffiRustCallStatusErrorHandler { + 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 uniffiRustCall(callback: (UniffiRustCallStatus) -> U): U { + return uniffiRustCallWithError(UniffiNullRustCallStatusErrorHandler, callback) +} + +internal inline fun uniffiTraitInterfaceCall( + callStatus: UniffiRustCallStatus, + makeCall: () -> T, + writeReturn: (T) -> Unit, +) { + try { + writeReturn(makeCall()) + } catch(e: kotlin.Exception) { + callStatus.code = UNIFFI_CALL_UNEXPECTED_ERROR + callStatus.error_buf = FfiConverterString.lower(e.toString()) + } +} + +internal inline fun uniffiTraitInterfaceCallWithError( + callStatus: UniffiRustCallStatus, + makeCall: () -> T, + writeReturn: (T) -> Unit, + lowerError: (E) -> RustBuffer.ByValue +) { + try { + writeReturn(makeCall()) + } catch(e: kotlin.Exception) { + if (e is E) { + callStatus.code = UNIFFI_CALL_ERROR + callStatus.error_buf = lowerError(e) + } else { + callStatus.code = UNIFFI_CALL_UNEXPECTED_ERROR + callStatus.error_buf = FfiConverterString.lower(e.toString()) + } + } +} +// Map handles to objects +// +// This is used pass an opaque 64-bit handle representing a foreign object to the Rust code. +internal class UniffiHandleMap { + private val map = ConcurrentHashMap() + private val counter = java.util.concurrent.atomic.AtomicLong(0) + + val size: Int + get() = map.size + + // Insert a new object into the handle map and get a handle for it + fun insert(obj: T): Long { + val handle = counter.getAndAdd(1) + map.put(handle, obj) + return handle + } + + // Get an object from the handle map + fun get(handle: Long): T { + return map.get(handle) ?: throw InternalException("UniffiHandleMap.get: Invalid handle") + } + + // Remove an entry from the handlemap and get the Kotlin object back + fun remove(handle: Long): T { + return map.remove(handle) ?: throw InternalException("UniffiHandleMap: Invalid handle") + } +} + +// 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 "skilly_core_mobile_sdk" +} + +private inline fun loadIndirect( + componentName: String +): Lib { + return Native.load(findLibraryName(componentName), Lib::class.java) +} + +// Define FFI callback types +internal interface UniffiRustFutureContinuationCallback : com.sun.jna.Callback { + fun callback(`data`: Long,`pollResult`: Byte,) +} +internal interface UniffiForeignFutureFree : com.sun.jna.Callback { + fun callback(`handle`: Long,) +} +internal interface UniffiCallbackInterfaceFree : com.sun.jna.Callback { + fun callback(`handle`: Long,) +} +@Structure.FieldOrder("handle", "free") +internal open class UniffiForeignFuture( + @JvmField internal var `handle`: Long = 0.toLong(), + @JvmField internal var `free`: UniffiForeignFutureFree? = null, +) : Structure() { + class UniffiByValue( + `handle`: Long = 0.toLong(), + `free`: UniffiForeignFutureFree? = null, + ): UniffiForeignFuture(`handle`,`free`,), Structure.ByValue + + internal fun uniffiSetValue(other: UniffiForeignFuture) { + `handle` = other.`handle` + `free` = other.`free` + } + +} +@Structure.FieldOrder("returnValue", "callStatus") +internal open class UniffiForeignFutureStructU8( + @JvmField internal var `returnValue`: Byte = 0.toByte(), + @JvmField internal var `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(), +) : Structure() { + class UniffiByValue( + `returnValue`: Byte = 0.toByte(), + `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(), + ): UniffiForeignFutureStructU8(`returnValue`,`callStatus`,), Structure.ByValue + + internal fun uniffiSetValue(other: UniffiForeignFutureStructU8) { + `returnValue` = other.`returnValue` + `callStatus` = other.`callStatus` + } + +} +internal interface UniffiForeignFutureCompleteU8 : com.sun.jna.Callback { + fun callback(`callbackData`: Long,`result`: UniffiForeignFutureStructU8.UniffiByValue,) +} +@Structure.FieldOrder("returnValue", "callStatus") +internal open class UniffiForeignFutureStructI8( + @JvmField internal var `returnValue`: Byte = 0.toByte(), + @JvmField internal var `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(), +) : Structure() { + class UniffiByValue( + `returnValue`: Byte = 0.toByte(), + `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(), + ): UniffiForeignFutureStructI8(`returnValue`,`callStatus`,), Structure.ByValue + + internal fun uniffiSetValue(other: UniffiForeignFutureStructI8) { + `returnValue` = other.`returnValue` + `callStatus` = other.`callStatus` + } + +} +internal interface UniffiForeignFutureCompleteI8 : com.sun.jna.Callback { + fun callback(`callbackData`: Long,`result`: UniffiForeignFutureStructI8.UniffiByValue,) +} +@Structure.FieldOrder("returnValue", "callStatus") +internal open class UniffiForeignFutureStructU16( + @JvmField internal var `returnValue`: Short = 0.toShort(), + @JvmField internal var `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(), +) : Structure() { + class UniffiByValue( + `returnValue`: Short = 0.toShort(), + `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(), + ): UniffiForeignFutureStructU16(`returnValue`,`callStatus`,), Structure.ByValue + + internal fun uniffiSetValue(other: UniffiForeignFutureStructU16) { + `returnValue` = other.`returnValue` + `callStatus` = other.`callStatus` + } + +} +internal interface UniffiForeignFutureCompleteU16 : com.sun.jna.Callback { + fun callback(`callbackData`: Long,`result`: UniffiForeignFutureStructU16.UniffiByValue,) +} +@Structure.FieldOrder("returnValue", "callStatus") +internal open class UniffiForeignFutureStructI16( + @JvmField internal var `returnValue`: Short = 0.toShort(), + @JvmField internal var `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(), +) : Structure() { + class UniffiByValue( + `returnValue`: Short = 0.toShort(), + `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(), + ): UniffiForeignFutureStructI16(`returnValue`,`callStatus`,), Structure.ByValue + + internal fun uniffiSetValue(other: UniffiForeignFutureStructI16) { + `returnValue` = other.`returnValue` + `callStatus` = other.`callStatus` + } + +} +internal interface UniffiForeignFutureCompleteI16 : com.sun.jna.Callback { + fun callback(`callbackData`: Long,`result`: UniffiForeignFutureStructI16.UniffiByValue,) +} +@Structure.FieldOrder("returnValue", "callStatus") +internal open class UniffiForeignFutureStructU32( + @JvmField internal var `returnValue`: Int = 0, + @JvmField internal var `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(), +) : Structure() { + class UniffiByValue( + `returnValue`: Int = 0, + `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(), + ): UniffiForeignFutureStructU32(`returnValue`,`callStatus`,), Structure.ByValue + + internal fun uniffiSetValue(other: UniffiForeignFutureStructU32) { + `returnValue` = other.`returnValue` + `callStatus` = other.`callStatus` + } + +} +internal interface UniffiForeignFutureCompleteU32 : com.sun.jna.Callback { + fun callback(`callbackData`: Long,`result`: UniffiForeignFutureStructU32.UniffiByValue,) +} +@Structure.FieldOrder("returnValue", "callStatus") +internal open class UniffiForeignFutureStructI32( + @JvmField internal var `returnValue`: Int = 0, + @JvmField internal var `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(), +) : Structure() { + class UniffiByValue( + `returnValue`: Int = 0, + `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(), + ): UniffiForeignFutureStructI32(`returnValue`,`callStatus`,), Structure.ByValue + + internal fun uniffiSetValue(other: UniffiForeignFutureStructI32) { + `returnValue` = other.`returnValue` + `callStatus` = other.`callStatus` + } + +} +internal interface UniffiForeignFutureCompleteI32 : com.sun.jna.Callback { + fun callback(`callbackData`: Long,`result`: UniffiForeignFutureStructI32.UniffiByValue,) +} +@Structure.FieldOrder("returnValue", "callStatus") +internal open class UniffiForeignFutureStructU64( + @JvmField internal var `returnValue`: Long = 0.toLong(), + @JvmField internal var `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(), +) : Structure() { + class UniffiByValue( + `returnValue`: Long = 0.toLong(), + `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(), + ): UniffiForeignFutureStructU64(`returnValue`,`callStatus`,), Structure.ByValue + + internal fun uniffiSetValue(other: UniffiForeignFutureStructU64) { + `returnValue` = other.`returnValue` + `callStatus` = other.`callStatus` + } + +} +internal interface UniffiForeignFutureCompleteU64 : com.sun.jna.Callback { + fun callback(`callbackData`: Long,`result`: UniffiForeignFutureStructU64.UniffiByValue,) +} +@Structure.FieldOrder("returnValue", "callStatus") +internal open class UniffiForeignFutureStructI64( + @JvmField internal var `returnValue`: Long = 0.toLong(), + @JvmField internal var `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(), +) : Structure() { + class UniffiByValue( + `returnValue`: Long = 0.toLong(), + `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(), + ): UniffiForeignFutureStructI64(`returnValue`,`callStatus`,), Structure.ByValue + + internal fun uniffiSetValue(other: UniffiForeignFutureStructI64) { + `returnValue` = other.`returnValue` + `callStatus` = other.`callStatus` + } + +} +internal interface UniffiForeignFutureCompleteI64 : com.sun.jna.Callback { + fun callback(`callbackData`: Long,`result`: UniffiForeignFutureStructI64.UniffiByValue,) +} +@Structure.FieldOrder("returnValue", "callStatus") +internal open class UniffiForeignFutureStructF32( + @JvmField internal var `returnValue`: Float = 0.0f, + @JvmField internal var `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(), +) : Structure() { + class UniffiByValue( + `returnValue`: Float = 0.0f, + `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(), + ): UniffiForeignFutureStructF32(`returnValue`,`callStatus`,), Structure.ByValue + + internal fun uniffiSetValue(other: UniffiForeignFutureStructF32) { + `returnValue` = other.`returnValue` + `callStatus` = other.`callStatus` + } + +} +internal interface UniffiForeignFutureCompleteF32 : com.sun.jna.Callback { + fun callback(`callbackData`: Long,`result`: UniffiForeignFutureStructF32.UniffiByValue,) +} +@Structure.FieldOrder("returnValue", "callStatus") +internal open class UniffiForeignFutureStructF64( + @JvmField internal var `returnValue`: Double = 0.0, + @JvmField internal var `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(), +) : Structure() { + class UniffiByValue( + `returnValue`: Double = 0.0, + `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(), + ): UniffiForeignFutureStructF64(`returnValue`,`callStatus`,), Structure.ByValue + + internal fun uniffiSetValue(other: UniffiForeignFutureStructF64) { + `returnValue` = other.`returnValue` + `callStatus` = other.`callStatus` + } + +} +internal interface UniffiForeignFutureCompleteF64 : com.sun.jna.Callback { + fun callback(`callbackData`: Long,`result`: UniffiForeignFutureStructF64.UniffiByValue,) +} +@Structure.FieldOrder("returnValue", "callStatus") +internal open class UniffiForeignFutureStructPointer( + @JvmField internal var `returnValue`: Pointer = Pointer.NULL, + @JvmField internal var `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(), +) : Structure() { + class UniffiByValue( + `returnValue`: Pointer = Pointer.NULL, + `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(), + ): UniffiForeignFutureStructPointer(`returnValue`,`callStatus`,), Structure.ByValue + + internal fun uniffiSetValue(other: UniffiForeignFutureStructPointer) { + `returnValue` = other.`returnValue` + `callStatus` = other.`callStatus` + } + +} +internal interface UniffiForeignFutureCompletePointer : com.sun.jna.Callback { + fun callback(`callbackData`: Long,`result`: UniffiForeignFutureStructPointer.UniffiByValue,) +} +@Structure.FieldOrder("returnValue", "callStatus") +internal open class UniffiForeignFutureStructRustBuffer( + @JvmField internal var `returnValue`: RustBuffer.ByValue = RustBuffer.ByValue(), + @JvmField internal var `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(), +) : Structure() { + class UniffiByValue( + `returnValue`: RustBuffer.ByValue = RustBuffer.ByValue(), + `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(), + ): UniffiForeignFutureStructRustBuffer(`returnValue`,`callStatus`,), Structure.ByValue + + internal fun uniffiSetValue(other: UniffiForeignFutureStructRustBuffer) { + `returnValue` = other.`returnValue` + `callStatus` = other.`callStatus` + } + +} +internal interface UniffiForeignFutureCompleteRustBuffer : com.sun.jna.Callback { + fun callback(`callbackData`: Long,`result`: UniffiForeignFutureStructRustBuffer.UniffiByValue,) +} +@Structure.FieldOrder("callStatus") +internal open class UniffiForeignFutureStructVoid( + @JvmField internal var `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(), +) : Structure() { + class UniffiByValue( + `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(), + ): UniffiForeignFutureStructVoid(`callStatus`,), Structure.ByValue + + internal fun uniffiSetValue(other: UniffiForeignFutureStructVoid) { + `callStatus` = other.`callStatus` + } + +} +internal interface UniffiForeignFutureCompleteVoid : com.sun.jna.Callback { + fun callback(`callbackData`: Long,`result`: UniffiForeignFutureStructVoid.UniffiByValue,) +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +// 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(componentName = "skilly_core_mobile_sdk") + .also { lib: UniffiLib -> + uniffiCheckContractApiVersion(lib) + uniffiCheckApiChecksums(lib) + } + } + + } + + fun uniffi_skilly_core_mobile_sdk_fn_func_can_start_turn_for_mobile(`input`: RustBuffer.ByValue,uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + fun uniffi_skilly_core_mobile_sdk_fn_func_replay_realtime_events_for_mobile(`events`: RustBuffer.ByValue,uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + fun uniffi_skilly_core_mobile_sdk_fn_func_replay_realtime_events_from_json_for_mobile(`eventsJson`: RustBuffer.ByValue,uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + fun uniffi_skilly_core_mobile_sdk_fn_func_trial_is_exhausted_for_mobile(`input`: RustBuffer.ByValue,uniffi_out_err: UniffiRustCallStatus, + ): Byte + fun uniffi_skilly_core_mobile_sdk_fn_func_usage_is_over_cap_for_mobile(`input`: RustBuffer.ByValue,uniffi_out_err: UniffiRustCallStatus, + ): Byte + fun ffi_skilly_core_mobile_sdk_rustbuffer_alloc(`size`: Long,uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + fun ffi_skilly_core_mobile_sdk_rustbuffer_from_bytes(`bytes`: ForeignBytes.ByValue,uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + fun ffi_skilly_core_mobile_sdk_rustbuffer_free(`buf`: RustBuffer.ByValue,uniffi_out_err: UniffiRustCallStatus, + ): Unit + fun ffi_skilly_core_mobile_sdk_rustbuffer_reserve(`buf`: RustBuffer.ByValue,`additional`: Long,uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + fun ffi_skilly_core_mobile_sdk_rust_future_poll_u8(`handle`: Long,`callback`: UniffiRustFutureContinuationCallback,`callbackData`: Long, + ): Unit + fun ffi_skilly_core_mobile_sdk_rust_future_cancel_u8(`handle`: Long, + ): Unit + fun ffi_skilly_core_mobile_sdk_rust_future_free_u8(`handle`: Long, + ): Unit + fun ffi_skilly_core_mobile_sdk_rust_future_complete_u8(`handle`: Long,uniffi_out_err: UniffiRustCallStatus, + ): Byte + fun ffi_skilly_core_mobile_sdk_rust_future_poll_i8(`handle`: Long,`callback`: UniffiRustFutureContinuationCallback,`callbackData`: Long, + ): Unit + fun ffi_skilly_core_mobile_sdk_rust_future_cancel_i8(`handle`: Long, + ): Unit + fun ffi_skilly_core_mobile_sdk_rust_future_free_i8(`handle`: Long, + ): Unit + fun ffi_skilly_core_mobile_sdk_rust_future_complete_i8(`handle`: Long,uniffi_out_err: UniffiRustCallStatus, + ): Byte + fun ffi_skilly_core_mobile_sdk_rust_future_poll_u16(`handle`: Long,`callback`: UniffiRustFutureContinuationCallback,`callbackData`: Long, + ): Unit + fun ffi_skilly_core_mobile_sdk_rust_future_cancel_u16(`handle`: Long, + ): Unit + fun ffi_skilly_core_mobile_sdk_rust_future_free_u16(`handle`: Long, + ): Unit + fun ffi_skilly_core_mobile_sdk_rust_future_complete_u16(`handle`: Long,uniffi_out_err: UniffiRustCallStatus, + ): Short + fun ffi_skilly_core_mobile_sdk_rust_future_poll_i16(`handle`: Long,`callback`: UniffiRustFutureContinuationCallback,`callbackData`: Long, + ): Unit + fun ffi_skilly_core_mobile_sdk_rust_future_cancel_i16(`handle`: Long, + ): Unit + fun ffi_skilly_core_mobile_sdk_rust_future_free_i16(`handle`: Long, + ): Unit + fun ffi_skilly_core_mobile_sdk_rust_future_complete_i16(`handle`: Long,uniffi_out_err: UniffiRustCallStatus, + ): Short + fun ffi_skilly_core_mobile_sdk_rust_future_poll_u32(`handle`: Long,`callback`: UniffiRustFutureContinuationCallback,`callbackData`: Long, + ): Unit + fun ffi_skilly_core_mobile_sdk_rust_future_cancel_u32(`handle`: Long, + ): Unit + fun ffi_skilly_core_mobile_sdk_rust_future_free_u32(`handle`: Long, + ): Unit + fun ffi_skilly_core_mobile_sdk_rust_future_complete_u32(`handle`: Long,uniffi_out_err: UniffiRustCallStatus, + ): Int + fun ffi_skilly_core_mobile_sdk_rust_future_poll_i32(`handle`: Long,`callback`: UniffiRustFutureContinuationCallback,`callbackData`: Long, + ): Unit + fun ffi_skilly_core_mobile_sdk_rust_future_cancel_i32(`handle`: Long, + ): Unit + fun ffi_skilly_core_mobile_sdk_rust_future_free_i32(`handle`: Long, + ): Unit + fun ffi_skilly_core_mobile_sdk_rust_future_complete_i32(`handle`: Long,uniffi_out_err: UniffiRustCallStatus, + ): Int + fun ffi_skilly_core_mobile_sdk_rust_future_poll_u64(`handle`: Long,`callback`: UniffiRustFutureContinuationCallback,`callbackData`: Long, + ): Unit + fun ffi_skilly_core_mobile_sdk_rust_future_cancel_u64(`handle`: Long, + ): Unit + fun ffi_skilly_core_mobile_sdk_rust_future_free_u64(`handle`: Long, + ): Unit + fun ffi_skilly_core_mobile_sdk_rust_future_complete_u64(`handle`: Long,uniffi_out_err: UniffiRustCallStatus, + ): Long + fun ffi_skilly_core_mobile_sdk_rust_future_poll_i64(`handle`: Long,`callback`: UniffiRustFutureContinuationCallback,`callbackData`: Long, + ): Unit + fun ffi_skilly_core_mobile_sdk_rust_future_cancel_i64(`handle`: Long, + ): Unit + fun ffi_skilly_core_mobile_sdk_rust_future_free_i64(`handle`: Long, + ): Unit + fun ffi_skilly_core_mobile_sdk_rust_future_complete_i64(`handle`: Long,uniffi_out_err: UniffiRustCallStatus, + ): Long + fun ffi_skilly_core_mobile_sdk_rust_future_poll_f32(`handle`: Long,`callback`: UniffiRustFutureContinuationCallback,`callbackData`: Long, + ): Unit + fun ffi_skilly_core_mobile_sdk_rust_future_cancel_f32(`handle`: Long, + ): Unit + fun ffi_skilly_core_mobile_sdk_rust_future_free_f32(`handle`: Long, + ): Unit + fun ffi_skilly_core_mobile_sdk_rust_future_complete_f32(`handle`: Long,uniffi_out_err: UniffiRustCallStatus, + ): Float + fun ffi_skilly_core_mobile_sdk_rust_future_poll_f64(`handle`: Long,`callback`: UniffiRustFutureContinuationCallback,`callbackData`: Long, + ): Unit + fun ffi_skilly_core_mobile_sdk_rust_future_cancel_f64(`handle`: Long, + ): Unit + fun ffi_skilly_core_mobile_sdk_rust_future_free_f64(`handle`: Long, + ): Unit + fun ffi_skilly_core_mobile_sdk_rust_future_complete_f64(`handle`: Long,uniffi_out_err: UniffiRustCallStatus, + ): Double + fun ffi_skilly_core_mobile_sdk_rust_future_poll_pointer(`handle`: Long,`callback`: UniffiRustFutureContinuationCallback,`callbackData`: Long, + ): Unit + fun ffi_skilly_core_mobile_sdk_rust_future_cancel_pointer(`handle`: Long, + ): Unit + fun ffi_skilly_core_mobile_sdk_rust_future_free_pointer(`handle`: Long, + ): Unit + fun ffi_skilly_core_mobile_sdk_rust_future_complete_pointer(`handle`: Long,uniffi_out_err: UniffiRustCallStatus, + ): Pointer + fun ffi_skilly_core_mobile_sdk_rust_future_poll_rust_buffer(`handle`: Long,`callback`: UniffiRustFutureContinuationCallback,`callbackData`: Long, + ): Unit + fun ffi_skilly_core_mobile_sdk_rust_future_cancel_rust_buffer(`handle`: Long, + ): Unit + fun ffi_skilly_core_mobile_sdk_rust_future_free_rust_buffer(`handle`: Long, + ): Unit + fun ffi_skilly_core_mobile_sdk_rust_future_complete_rust_buffer(`handle`: Long,uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + fun ffi_skilly_core_mobile_sdk_rust_future_poll_void(`handle`: Long,`callback`: UniffiRustFutureContinuationCallback,`callbackData`: Long, + ): Unit + fun ffi_skilly_core_mobile_sdk_rust_future_cancel_void(`handle`: Long, + ): Unit + fun ffi_skilly_core_mobile_sdk_rust_future_free_void(`handle`: Long, + ): Unit + fun ffi_skilly_core_mobile_sdk_rust_future_complete_void(`handle`: Long,uniffi_out_err: UniffiRustCallStatus, + ): Unit + fun uniffi_skilly_core_mobile_sdk_checksum_func_can_start_turn_for_mobile( + ): Short + fun uniffi_skilly_core_mobile_sdk_checksum_func_replay_realtime_events_for_mobile( + ): Short + fun uniffi_skilly_core_mobile_sdk_checksum_func_replay_realtime_events_from_json_for_mobile( + ): Short + fun uniffi_skilly_core_mobile_sdk_checksum_func_trial_is_exhausted_for_mobile( + ): Short + fun uniffi_skilly_core_mobile_sdk_checksum_func_usage_is_over_cap_for_mobile( + ): Short + fun ffi_skilly_core_mobile_sdk_uniffi_contract_version( + ): Int + +} + +private fun uniffiCheckContractApiVersion(lib: UniffiLib) { + // Get the bindings contract version from our ComponentInterface + val bindings_contract_version = 26 + // Get the scaffolding contract version by calling the into the dylib + val scaffolding_contract_version = lib.ffi_skilly_core_mobile_sdk_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_skilly_core_mobile_sdk_checksum_func_can_start_turn_for_mobile() != 55318.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_skilly_core_mobile_sdk_checksum_func_replay_realtime_events_for_mobile() != 3997.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_skilly_core_mobile_sdk_checksum_func_replay_realtime_events_from_json_for_mobile() != 42033.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_skilly_core_mobile_sdk_checksum_func_trial_is_exhausted_for_mobile() != 1523.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_skilly_core_mobile_sdk_checksum_func_usage_is_over_cap_for_mobile() != 40273.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } +} + +// Async support + +// Public interface members begin here. + + +// Interface implemented by anything that can contain an object reference. +// +// Such types expose a `destroy()` method that must be called to cleanly +// dispose of the contained objects. Failure to call this method may result +// in memory leaks. +// +// The easiest way to ensure this method is called is to use the `.use` +// helper method to execute a block and destroy the object at the end. +interface Disposable { + fun destroy() + companion object { + fun destroy(vararg args: Any?) { + args.filterIsInstance() + .forEach(Disposable::destroy) + } + } +} + +/** + * @suppress + */ +inline fun T.use(block: (T) -> R) = + try { + block(this) + } finally { + try { + // N.B. our implementation is on the nullable type `Disposable?`. + this?.destroy() + } catch (e: Throwable) { + // swallow + } + } + +/** + * Used to instantiate an interface without an actual pointer, for fakes in tests, mostly. + * + * @suppress + * */ +object NoPointer + +/** + * @suppress + */ +public object FfiConverterULong: FfiConverter { + override fun lift(value: Long): ULong { + return value.toULong() + } + + override fun read(buf: ByteBuffer): ULong { + return lift(buf.getLong()) + } + + override fun lower(value: ULong): Long { + return value.toLong() + } + + override fun allocationSize(value: ULong) = 8UL + + override fun write(value: ULong, buf: ByteBuffer) { + buf.putLong(value.toLong()) + } +} + +/** + * @suppress + */ +public object FfiConverterBoolean: FfiConverter { + override fun lift(value: Byte): Boolean { + return value.toInt() != 0 + } + + override fun read(buf: ByteBuffer): Boolean { + return lift(buf.get()) + } + + override fun lower(value: Boolean): Byte { + return if (value) 1.toByte() else 0.toByte() + } + + override fun allocationSize(value: Boolean) = 1UL + + override fun write(value: Boolean, buf: ByteBuffer) { + buf.put(lower(value)) + } +} + +/** + * @suppress + */ +public object FfiConverterString: FfiConverter { + // 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.toInt()) + 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().toULong()) + 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): ULong { + val sizeForLength = 4UL + val sizeForString = value.length.toULong() * 3UL + return sizeForLength + sizeForString + } + + override fun write(value: String, buf: ByteBuffer) { + val byteBuf = toUtf8(value) + buf.putInt(byteBuf.limit()) + buf.put(byteBuf) + } +} + + + +data class MobilePolicyDecision ( + var `allowed`: kotlin.Boolean, + var `reason`: MobileBlockReason?, + var `isAdminUser`: kotlin.Boolean +) { + + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypeMobilePolicyDecision: FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): MobilePolicyDecision { + return MobilePolicyDecision( + FfiConverterBoolean.read(buf), + FfiConverterOptionalTypeMobileBlockReason.read(buf), + FfiConverterBoolean.read(buf), + ) + } + + override fun allocationSize(value: MobilePolicyDecision) = ( + FfiConverterBoolean.allocationSize(value.`allowed`) + + FfiConverterOptionalTypeMobileBlockReason.allocationSize(value.`reason`) + + FfiConverterBoolean.allocationSize(value.`isAdminUser`) + ) + + override fun write(value: MobilePolicyDecision, buf: ByteBuffer) { + FfiConverterBoolean.write(value.`allowed`, buf) + FfiConverterOptionalTypeMobileBlockReason.write(value.`reason`, buf) + FfiConverterBoolean.write(value.`isAdminUser`, buf) + } +} + + + +data class MobilePolicyInput ( + var `userId`: kotlin.String?, + var `entitlementState`: MobileEntitlementState, + var `trialSecondsUsed`: kotlin.ULong, + var `usageSecondsUsed`: kotlin.ULong, + var `adminWorkosUserIds`: List +) { + + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypeMobilePolicyInput: FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): MobilePolicyInput { + return MobilePolicyInput( + FfiConverterOptionalString.read(buf), + FfiConverterTypeMobileEntitlementState.read(buf), + FfiConverterULong.read(buf), + FfiConverterULong.read(buf), + FfiConverterSequenceString.read(buf), + ) + } + + override fun allocationSize(value: MobilePolicyInput) = ( + FfiConverterOptionalString.allocationSize(value.`userId`) + + FfiConverterTypeMobileEntitlementState.allocationSize(value.`entitlementState`) + + FfiConverterULong.allocationSize(value.`trialSecondsUsed`) + + FfiConverterULong.allocationSize(value.`usageSecondsUsed`) + + FfiConverterSequenceString.allocationSize(value.`adminWorkosUserIds`) + ) + + override fun write(value: MobilePolicyInput, buf: ByteBuffer) { + FfiConverterOptionalString.write(value.`userId`, buf) + FfiConverterTypeMobileEntitlementState.write(value.`entitlementState`, buf) + FfiConverterULong.write(value.`trialSecondsUsed`, buf) + FfiConverterULong.write(value.`usageSecondsUsed`, buf) + FfiConverterSequenceString.write(value.`adminWorkosUserIds`, buf) + } +} + + + +data class MobileRealtimeEvent ( + var `eventType`: MobileRealtimeEventType, + var `turnId`: kotlin.String?, + var `message`: kotlin.String? +) { + + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypeMobileRealtimeEvent: FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): MobileRealtimeEvent { + return MobileRealtimeEvent( + FfiConverterTypeMobileRealtimeEventType.read(buf), + FfiConverterOptionalString.read(buf), + FfiConverterOptionalString.read(buf), + ) + } + + override fun allocationSize(value: MobileRealtimeEvent) = ( + FfiConverterTypeMobileRealtimeEventType.allocationSize(value.`eventType`) + + FfiConverterOptionalString.allocationSize(value.`turnId`) + + FfiConverterOptionalString.allocationSize(value.`message`) + ) + + override fun write(value: MobileRealtimeEvent, buf: ByteBuffer) { + FfiConverterTypeMobileRealtimeEventType.write(value.`eventType`, buf) + FfiConverterOptionalString.write(value.`turnId`, buf) + FfiConverterOptionalString.write(value.`message`, buf) + } +} + + + +data class MobileRealtimeReplaySummary ( + var `phaseName`: kotlin.String, + var `turnsCompleted`: kotlin.ULong +) { + + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypeMobileRealtimeReplaySummary: FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): MobileRealtimeReplaySummary { + return MobileRealtimeReplaySummary( + FfiConverterString.read(buf), + FfiConverterULong.read(buf), + ) + } + + override fun allocationSize(value: MobileRealtimeReplaySummary) = ( + FfiConverterString.allocationSize(value.`phaseName`) + + FfiConverterULong.allocationSize(value.`turnsCompleted`) + ) + + override fun write(value: MobileRealtimeReplaySummary, buf: ByteBuffer) { + FfiConverterString.write(value.`phaseName`, buf) + FfiConverterULong.write(value.`turnsCompleted`, buf) + } +} + + + + +enum class MobileBlockReason { + + TRIAL_EXHAUSTED, + CAP_REACHED, + SUBSCRIPTION_INACTIVE, + EXPIRED; + companion object +} + + +/** + * @suppress + */ +public object FfiConverterTypeMobileBlockReason: FfiConverterRustBuffer { + override fun read(buf: ByteBuffer) = try { + MobileBlockReason.values()[buf.getInt() - 1] + } catch (e: IndexOutOfBoundsException) { + throw RuntimeException("invalid enum value, something is very wrong!!", e) + } + + override fun allocationSize(value: MobileBlockReason) = 4UL + + override fun write(value: MobileBlockReason, buf: ByteBuffer) { + buf.putInt(value.ordinal + 1) + } +} + + + + + + +enum class MobileEntitlementState { + + NONE, + TRIAL, + ACTIVE, + CANCELED_VALID, + CANCELED_EXPIRED, + EXPIRED; + companion object +} + + +/** + * @suppress + */ +public object FfiConverterTypeMobileEntitlementState: FfiConverterRustBuffer { + override fun read(buf: ByteBuffer) = try { + MobileEntitlementState.values()[buf.getInt() - 1] + } catch (e: IndexOutOfBoundsException) { + throw RuntimeException("invalid enum value, something is very wrong!!", e) + } + + override fun allocationSize(value: MobileEntitlementState) = 4UL + + override fun write(value: MobileEntitlementState, buf: ByteBuffer) { + buf.putInt(value.ordinal + 1) + } +} + + + + + + +enum class MobileRealtimeEventType { + + TURN_STARTED, + AUDIO_CAPTURE_COMMITTED, + RESPONSE_STARTED, + AUDIO_PLAYBACK_STARTED, + RESPONSE_COMPLETED, + SESSION_ERROR, + SESSION_RESET; + companion object +} + + +/** + * @suppress + */ +public object FfiConverterTypeMobileRealtimeEventType: FfiConverterRustBuffer { + override fun read(buf: ByteBuffer) = try { + MobileRealtimeEventType.values()[buf.getInt() - 1] + } catch (e: IndexOutOfBoundsException) { + throw RuntimeException("invalid enum value, something is very wrong!!", e) + } + + override fun allocationSize(value: MobileRealtimeEventType) = 4UL + + override fun write(value: MobileRealtimeEventType, buf: ByteBuffer) { + buf.putInt(value.ordinal + 1) + } +} + + + + + + +/** + * @suppress + */ +public object FfiConverterOptionalString: FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): kotlin.String? { + if (buf.get().toInt() == 0) { + return null + } + return FfiConverterString.read(buf) + } + + override fun allocationSize(value: kotlin.String?): ULong { + if (value == null) { + return 1UL + } else { + return 1UL + FfiConverterString.allocationSize(value) + } + } + + override fun write(value: kotlin.String?, buf: ByteBuffer) { + if (value == null) { + buf.put(0) + } else { + buf.put(1) + FfiConverterString.write(value, buf) + } + } +} + + + + +/** + * @suppress + */ +public object FfiConverterOptionalTypeMobileRealtimeReplaySummary: FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): MobileRealtimeReplaySummary? { + if (buf.get().toInt() == 0) { + return null + } + return FfiConverterTypeMobileRealtimeReplaySummary.read(buf) + } + + override fun allocationSize(value: MobileRealtimeReplaySummary?): ULong { + if (value == null) { + return 1UL + } else { + return 1UL + FfiConverterTypeMobileRealtimeReplaySummary.allocationSize(value) + } + } + + override fun write(value: MobileRealtimeReplaySummary?, buf: ByteBuffer) { + if (value == null) { + buf.put(0) + } else { + buf.put(1) + FfiConverterTypeMobileRealtimeReplaySummary.write(value, buf) + } + } +} + + + + +/** + * @suppress + */ +public object FfiConverterOptionalTypeMobileBlockReason: FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): MobileBlockReason? { + if (buf.get().toInt() == 0) { + return null + } + return FfiConverterTypeMobileBlockReason.read(buf) + } + + override fun allocationSize(value: MobileBlockReason?): ULong { + if (value == null) { + return 1UL + } else { + return 1UL + FfiConverterTypeMobileBlockReason.allocationSize(value) + } + } + + override fun write(value: MobileBlockReason?, buf: ByteBuffer) { + if (value == null) { + buf.put(0) + } else { + buf.put(1) + FfiConverterTypeMobileBlockReason.write(value, buf) + } + } +} + + + + +/** + * @suppress + */ +public object FfiConverterSequenceString: FfiConverterRustBuffer> { + override fun read(buf: ByteBuffer): List { + val len = buf.getInt() + return List(len) { + FfiConverterString.read(buf) + } + } + + override fun allocationSize(value: List): ULong { + val sizeForLength = 4UL + val sizeForItems = value.map { FfiConverterString.allocationSize(it) }.sum() + return sizeForLength + sizeForItems + } + + override fun write(value: List, buf: ByteBuffer) { + buf.putInt(value.size) + value.iterator().forEach { + FfiConverterString.write(it, buf) + } + } +} + + + + +/** + * @suppress + */ +public object FfiConverterSequenceTypeMobileRealtimeEvent: FfiConverterRustBuffer> { + override fun read(buf: ByteBuffer): List { + val len = buf.getInt() + return List(len) { + FfiConverterTypeMobileRealtimeEvent.read(buf) + } + } + + override fun allocationSize(value: List): ULong { + val sizeForLength = 4UL + val sizeForItems = value.map { FfiConverterTypeMobileRealtimeEvent.allocationSize(it) }.sum() + return sizeForLength + sizeForItems + } + + override fun write(value: List, buf: ByteBuffer) { + buf.putInt(value.size) + value.iterator().forEach { + FfiConverterTypeMobileRealtimeEvent.write(it, buf) + } + } +} fun `canStartTurnForMobile`(`input`: MobilePolicyInput): MobilePolicyDecision { + return FfiConverterTypeMobilePolicyDecision.lift( + uniffiRustCall() { _status -> + UniffiLib.INSTANCE.uniffi_skilly_core_mobile_sdk_fn_func_can_start_turn_for_mobile( + FfiConverterTypeMobilePolicyInput.lower(`input`),_status) +} + ) + } + + fun `replayRealtimeEventsForMobile`(`events`: List): MobileRealtimeReplaySummary? { + return FfiConverterOptionalTypeMobileRealtimeReplaySummary.lift( + uniffiRustCall() { _status -> + UniffiLib.INSTANCE.uniffi_skilly_core_mobile_sdk_fn_func_replay_realtime_events_for_mobile( + FfiConverterSequenceTypeMobileRealtimeEvent.lower(`events`),_status) +} + ) + } + + fun `replayRealtimeEventsFromJsonForMobile`(`eventsJson`: kotlin.String): MobileRealtimeReplaySummary? { + return FfiConverterOptionalTypeMobileRealtimeReplaySummary.lift( + uniffiRustCall() { _status -> + UniffiLib.INSTANCE.uniffi_skilly_core_mobile_sdk_fn_func_replay_realtime_events_from_json_for_mobile( + FfiConverterString.lower(`eventsJson`),_status) +} + ) + } + + fun `trialIsExhaustedForMobile`(`input`: MobilePolicyInput): kotlin.Boolean { + return FfiConverterBoolean.lift( + uniffiRustCall() { _status -> + UniffiLib.INSTANCE.uniffi_skilly_core_mobile_sdk_fn_func_trial_is_exhausted_for_mobile( + FfiConverterTypeMobilePolicyInput.lower(`input`),_status) +} + ) + } + + fun `usageIsOverCapForMobile`(`input`: MobilePolicyInput): kotlin.Boolean { + return FfiConverterBoolean.lift( + uniffiRustCall() { _status -> + UniffiLib.INSTANCE.uniffi_skilly_core_mobile_sdk_fn_func_usage_is_over_cap_for_mobile( + FfiConverterTypeMobilePolicyInput.lower(`input`),_status) +} + ) + } + + + diff --git a/sdk/android/sample/src/main/kotlin/app/tryskilly/sdk/PolicyAndRealtimeExample.kt b/sdk/android/sample/src/main/kotlin/app/tryskilly/sdk/PolicyAndRealtimeExample.kt new file mode 100644 index 00000000..447ad3de --- /dev/null +++ b/sdk/android/sample/src/main/kotlin/app/tryskilly/sdk/PolicyAndRealtimeExample.kt @@ -0,0 +1,34 @@ +package app.tryskilly.sdk + +// This sample assumes the generated UniFFI Kotlin files from sdk/android/generated +// are added to your Android module source set. +import uniffi.skilly_core_mobile_sdk.* + +object PolicyAndRealtimeExample { + fun runDemo() { + val policyInput = MobilePolicyInput( + userId = "android-user-123", + entitlementState = MobileEntitlementState.TRIAL, + trialSecondsUsed = 400UL, + usageSecondsUsed = 0UL, + adminWorkosUserIds = emptyList() + ) + + val policyDecision = canStartTurnForMobile(policyInput) + println("Allowed=${policyDecision.allowed}, reason=${policyDecision.reason}") + + val events = listOf( + MobileRealtimeEvent(MobileRealtimeEventType.TURN_STARTED, "turn-android-1", null), + MobileRealtimeEvent(MobileRealtimeEventType.AUDIO_CAPTURE_COMMITTED, "turn-android-1", null), + MobileRealtimeEvent(MobileRealtimeEventType.RESPONSE_STARTED, "turn-android-1", null), + MobileRealtimeEvent(MobileRealtimeEventType.RESPONSE_COMPLETED, "turn-android-1", null) + ) + + val summary = replayRealtimeEventsForMobile(events) + if (summary != null) { + println("Phase=${summary.phaseName}, turnsCompleted=${summary.turnsCompleted}") + } else { + println("Replay failed") + } + } +} diff --git a/sdk/ios/README.md b/sdk/ios/README.md new file mode 100644 index 00000000..00cadac0 --- /dev/null +++ b/sdk/ios/README.md @@ -0,0 +1,10 @@ +# iOS SDK Artifacts + +- `generated/`: Swift bindings generated by UniFFI. +- `sample/`: sample Swift usage of generated APIs. + +## Regenerate + +```bash +./scripts/generate-mobile-sdk-bindings.sh +``` diff --git a/sdk/ios/generated/skilly_core_mobile_sdk.swift b/sdk/ios/generated/skilly_core_mobile_sdk.swift new file mode 100644 index 00000000..9e4371f6 --- /dev/null +++ b/sdk/ios/generated/skilly_core_mobile_sdk.swift @@ -0,0 +1,1255 @@ +// This file was autogenerated by some hot garbage in the `uniffi` crate. +// Trust me, you don't want to mess with it! + +// swiftlint:disable all +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(skilly_core_mobile_sdkFFI) +import skilly_core_mobile_sdkFFI +#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 empty() -> RustBuffer { + RustBuffer(capacity: 0, len:0, data: nil) + } + + static func from(_ ptr: UnsafeBufferPointer) -> RustBuffer { + try! rustCall { ffi_skilly_core_mobile_sdk_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_skilly_core_mobile_sdk_rustbuffer_free(self, $0) } + } +} + +fileprivate extension ForeignBytes { + init(bufferPointer: UnsafeBufferPointer) { + 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) { + self.init( + bytesNoCopy: rustBuffer.data!, + count: Int(rustBuffer.len), + deallocator: .none + ) + } +} + +// 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(_ reader: inout (data: Data, offset: Data.Index)) throws -> T { + let range = reader.offset...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 { + 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(_ 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(_ 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 to 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 { +#if swift(>=5.8) + @_documentation(visibility: private) +#endif + public static func lift(_ value: FfiType) throws -> SwiftType { + return value + } + +#if swift(>=5.8) + @_documentation(visibility: private) +#endif + 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 { +#if swift(>=5.8) + @_documentation(visibility: private) +#endif + 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 + } + +#if swift(>=5.8) + @_documentation(visibility: private) +#endif + 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 extension NSLock { + func withLock(f: () throws -> T) rethrows -> T { + self.lock() + defer { self.unlock() } + return try f() + } +} + +fileprivate let CALL_SUCCESS: Int8 = 0 +fileprivate let CALL_ERROR: Int8 = 1 +fileprivate let CALL_UNEXPECTED_ERROR: 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(_ callback: (UnsafeMutablePointer) -> T) throws -> T { + let neverThrow: ((RustBuffer) throws -> Never)? = nil + return try makeRustCall(callback, errorHandler: neverThrow) +} + +private func rustCallWithError( + _ errorHandler: @escaping (RustBuffer) throws -> E, + _ callback: (UnsafeMutablePointer) -> T) throws -> T { + try makeRustCall(callback, errorHandler: errorHandler) +} + +private func makeRustCall( + _ callback: (UnsafeMutablePointer) -> T, + errorHandler: ((RustBuffer) throws -> E)? +) 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 -> E)? +) 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_UNEXPECTED_ERROR: + // 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: + fatalError("Cancellation not supported yet") + + default: + throw UniffiInternalError.unexpectedRustCallStatusCode + } +} + +private func uniffiTraitInterfaceCall( + callStatus: UnsafeMutablePointer, + makeCall: () throws -> T, + writeReturn: (T) -> () +) { + do { + try writeReturn(makeCall()) + } catch let error { + callStatus.pointee.code = CALL_UNEXPECTED_ERROR + callStatus.pointee.errorBuf = FfiConverterString.lower(String(describing: error)) + } +} + +private func uniffiTraitInterfaceCallWithError( + callStatus: UnsafeMutablePointer, + makeCall: () throws -> T, + writeReturn: (T) -> (), + lowerError: (E) -> RustBuffer +) { + do { + try writeReturn(makeCall()) + } catch let error as E { + callStatus.pointee.code = CALL_ERROR + callStatus.pointee.errorBuf = lowerError(error) + } catch { + callStatus.pointee.code = CALL_UNEXPECTED_ERROR + callStatus.pointee.errorBuf = FfiConverterString.lower(String(describing: error)) + } +} +fileprivate class UniffiHandleMap { + private var map: [UInt64: T] = [:] + private let lock = NSLock() + private var currentHandle: UInt64 = 1 + + func insert(obj: T) -> UInt64 { + lock.withLock { + let handle = currentHandle + currentHandle += 1 + map[handle] = obj + return handle + } + } + + func get(handle: UInt64) throws -> T { + try lock.withLock { + guard let obj = map[handle] else { + throw UniffiInternalError.unexpectedStaleHandle + } + return obj + } + } + + @discardableResult + func remove(handle: UInt64) throws -> T { + try lock.withLock { + guard let obj = map.removeValue(forKey: handle) else { + throw UniffiInternalError.unexpectedStaleHandle + } + return obj + } + } + + var count: Int { + get { + map.count + } + } +} + + +// Public interface members begin here. + + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +fileprivate struct FfiConverterUInt64: FfiConverterPrimitive { + typealias FfiType = UInt64 + typealias SwiftType = UInt64 + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> UInt64 { + return try lift(readInt(&buf)) + } + + public static func write(_ value: SwiftType, into buf: inout [UInt8]) { + writeInt(&buf, lower(value)) + } +} + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +fileprivate struct FfiConverterBool : FfiConverter { + typealias FfiType = Int8 + typealias SwiftType = Bool + + public static func lift(_ value: Int8) throws -> Bool { + return value != 0 + } + + public static func lower(_ value: Bool) -> Int8 { + return value ? 1 : 0 + } + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> Bool { + return try lift(readInt(&buf)) + } + + public static func write(_ value: Bool, into buf: inout [UInt8]) { + writeInt(&buf, lower(value)) + } +} + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +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(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) + } +} + + +public struct MobilePolicyDecision { + public var allowed: Bool + public var reason: MobileBlockReason? + public var isAdminUser: Bool + + // Default memberwise initializers are never public by default, so we + // declare one manually. + public init(allowed: Bool, reason: MobileBlockReason?, isAdminUser: Bool) { + self.allowed = allowed + self.reason = reason + self.isAdminUser = isAdminUser + } +} + + + +extension MobilePolicyDecision: Equatable, Hashable { + public static func ==(lhs: MobilePolicyDecision, rhs: MobilePolicyDecision) -> Bool { + if lhs.allowed != rhs.allowed { + return false + } + if lhs.reason != rhs.reason { + return false + } + if lhs.isAdminUser != rhs.isAdminUser { + return false + } + return true + } + + public func hash(into hasher: inout Hasher) { + hasher.combine(allowed) + hasher.combine(reason) + hasher.combine(isAdminUser) + } +} + + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +public struct FfiConverterTypeMobilePolicyDecision: FfiConverterRustBuffer { + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> MobilePolicyDecision { + return + try MobilePolicyDecision( + allowed: FfiConverterBool.read(from: &buf), + reason: FfiConverterOptionTypeMobileBlockReason.read(from: &buf), + isAdminUser: FfiConverterBool.read(from: &buf) + ) + } + + public static func write(_ value: MobilePolicyDecision, into buf: inout [UInt8]) { + FfiConverterBool.write(value.allowed, into: &buf) + FfiConverterOptionTypeMobileBlockReason.write(value.reason, into: &buf) + FfiConverterBool.write(value.isAdminUser, into: &buf) + } +} + + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +public func FfiConverterTypeMobilePolicyDecision_lift(_ buf: RustBuffer) throws -> MobilePolicyDecision { + return try FfiConverterTypeMobilePolicyDecision.lift(buf) +} + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +public func FfiConverterTypeMobilePolicyDecision_lower(_ value: MobilePolicyDecision) -> RustBuffer { + return FfiConverterTypeMobilePolicyDecision.lower(value) +} + + +public struct MobilePolicyInput { + public var userId: String? + public var entitlementState: MobileEntitlementState + public var trialSecondsUsed: UInt64 + public var usageSecondsUsed: UInt64 + public var adminWorkosUserIds: [String] + + // Default memberwise initializers are never public by default, so we + // declare one manually. + public init(userId: String?, entitlementState: MobileEntitlementState, trialSecondsUsed: UInt64, usageSecondsUsed: UInt64, adminWorkosUserIds: [String]) { + self.userId = userId + self.entitlementState = entitlementState + self.trialSecondsUsed = trialSecondsUsed + self.usageSecondsUsed = usageSecondsUsed + self.adminWorkosUserIds = adminWorkosUserIds + } +} + + + +extension MobilePolicyInput: Equatable, Hashable { + public static func ==(lhs: MobilePolicyInput, rhs: MobilePolicyInput) -> Bool { + if lhs.userId != rhs.userId { + return false + } + if lhs.entitlementState != rhs.entitlementState { + return false + } + if lhs.trialSecondsUsed != rhs.trialSecondsUsed { + return false + } + if lhs.usageSecondsUsed != rhs.usageSecondsUsed { + return false + } + if lhs.adminWorkosUserIds != rhs.adminWorkosUserIds { + return false + } + return true + } + + public func hash(into hasher: inout Hasher) { + hasher.combine(userId) + hasher.combine(entitlementState) + hasher.combine(trialSecondsUsed) + hasher.combine(usageSecondsUsed) + hasher.combine(adminWorkosUserIds) + } +} + + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +public struct FfiConverterTypeMobilePolicyInput: FfiConverterRustBuffer { + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> MobilePolicyInput { + return + try MobilePolicyInput( + userId: FfiConverterOptionString.read(from: &buf), + entitlementState: FfiConverterTypeMobileEntitlementState.read(from: &buf), + trialSecondsUsed: FfiConverterUInt64.read(from: &buf), + usageSecondsUsed: FfiConverterUInt64.read(from: &buf), + adminWorkosUserIds: FfiConverterSequenceString.read(from: &buf) + ) + } + + public static func write(_ value: MobilePolicyInput, into buf: inout [UInt8]) { + FfiConverterOptionString.write(value.userId, into: &buf) + FfiConverterTypeMobileEntitlementState.write(value.entitlementState, into: &buf) + FfiConverterUInt64.write(value.trialSecondsUsed, into: &buf) + FfiConverterUInt64.write(value.usageSecondsUsed, into: &buf) + FfiConverterSequenceString.write(value.adminWorkosUserIds, into: &buf) + } +} + + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +public func FfiConverterTypeMobilePolicyInput_lift(_ buf: RustBuffer) throws -> MobilePolicyInput { + return try FfiConverterTypeMobilePolicyInput.lift(buf) +} + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +public func FfiConverterTypeMobilePolicyInput_lower(_ value: MobilePolicyInput) -> RustBuffer { + return FfiConverterTypeMobilePolicyInput.lower(value) +} + + +public struct MobileRealtimeEvent { + public var eventType: MobileRealtimeEventType + public var turnId: String? + public var message: String? + + // Default memberwise initializers are never public by default, so we + // declare one manually. + public init(eventType: MobileRealtimeEventType, turnId: String?, message: String?) { + self.eventType = eventType + self.turnId = turnId + self.message = message + } +} + + + +extension MobileRealtimeEvent: Equatable, Hashable { + public static func ==(lhs: MobileRealtimeEvent, rhs: MobileRealtimeEvent) -> Bool { + if lhs.eventType != rhs.eventType { + return false + } + if lhs.turnId != rhs.turnId { + return false + } + if lhs.message != rhs.message { + return false + } + return true + } + + public func hash(into hasher: inout Hasher) { + hasher.combine(eventType) + hasher.combine(turnId) + hasher.combine(message) + } +} + + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +public struct FfiConverterTypeMobileRealtimeEvent: FfiConverterRustBuffer { + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> MobileRealtimeEvent { + return + try MobileRealtimeEvent( + eventType: FfiConverterTypeMobileRealtimeEventType.read(from: &buf), + turnId: FfiConverterOptionString.read(from: &buf), + message: FfiConverterOptionString.read(from: &buf) + ) + } + + public static func write(_ value: MobileRealtimeEvent, into buf: inout [UInt8]) { + FfiConverterTypeMobileRealtimeEventType.write(value.eventType, into: &buf) + FfiConverterOptionString.write(value.turnId, into: &buf) + FfiConverterOptionString.write(value.message, into: &buf) + } +} + + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +public func FfiConverterTypeMobileRealtimeEvent_lift(_ buf: RustBuffer) throws -> MobileRealtimeEvent { + return try FfiConverterTypeMobileRealtimeEvent.lift(buf) +} + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +public func FfiConverterTypeMobileRealtimeEvent_lower(_ value: MobileRealtimeEvent) -> RustBuffer { + return FfiConverterTypeMobileRealtimeEvent.lower(value) +} + + +public struct MobileRealtimeReplaySummary { + public var phaseName: String + public var turnsCompleted: UInt64 + + // Default memberwise initializers are never public by default, so we + // declare one manually. + public init(phaseName: String, turnsCompleted: UInt64) { + self.phaseName = phaseName + self.turnsCompleted = turnsCompleted + } +} + + + +extension MobileRealtimeReplaySummary: Equatable, Hashable { + public static func ==(lhs: MobileRealtimeReplaySummary, rhs: MobileRealtimeReplaySummary) -> Bool { + if lhs.phaseName != rhs.phaseName { + return false + } + if lhs.turnsCompleted != rhs.turnsCompleted { + return false + } + return true + } + + public func hash(into hasher: inout Hasher) { + hasher.combine(phaseName) + hasher.combine(turnsCompleted) + } +} + + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +public struct FfiConverterTypeMobileRealtimeReplaySummary: FfiConverterRustBuffer { + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> MobileRealtimeReplaySummary { + return + try MobileRealtimeReplaySummary( + phaseName: FfiConverterString.read(from: &buf), + turnsCompleted: FfiConverterUInt64.read(from: &buf) + ) + } + + public static func write(_ value: MobileRealtimeReplaySummary, into buf: inout [UInt8]) { + FfiConverterString.write(value.phaseName, into: &buf) + FfiConverterUInt64.write(value.turnsCompleted, into: &buf) + } +} + + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +public func FfiConverterTypeMobileRealtimeReplaySummary_lift(_ buf: RustBuffer) throws -> MobileRealtimeReplaySummary { + return try FfiConverterTypeMobileRealtimeReplaySummary.lift(buf) +} + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +public func FfiConverterTypeMobileRealtimeReplaySummary_lower(_ value: MobileRealtimeReplaySummary) -> RustBuffer { + return FfiConverterTypeMobileRealtimeReplaySummary.lower(value) +} + +// Note that we don't yet support `indirect` for enums. +// See https://github.com/mozilla/uniffi-rs/issues/396 for further discussion. + +public enum MobileBlockReason { + + case trialExhausted + case capReached + case subscriptionInactive + case expired +} + + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +public struct FfiConverterTypeMobileBlockReason: FfiConverterRustBuffer { + typealias SwiftType = MobileBlockReason + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> MobileBlockReason { + let variant: Int32 = try readInt(&buf) + switch variant { + + case 1: return .trialExhausted + + case 2: return .capReached + + case 3: return .subscriptionInactive + + case 4: return .expired + + default: throw UniffiInternalError.unexpectedEnumCase + } + } + + public static func write(_ value: MobileBlockReason, into buf: inout [UInt8]) { + switch value { + + + case .trialExhausted: + writeInt(&buf, Int32(1)) + + + case .capReached: + writeInt(&buf, Int32(2)) + + + case .subscriptionInactive: + writeInt(&buf, Int32(3)) + + + case .expired: + writeInt(&buf, Int32(4)) + + } + } +} + + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +public func FfiConverterTypeMobileBlockReason_lift(_ buf: RustBuffer) throws -> MobileBlockReason { + return try FfiConverterTypeMobileBlockReason.lift(buf) +} + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +public func FfiConverterTypeMobileBlockReason_lower(_ value: MobileBlockReason) -> RustBuffer { + return FfiConverterTypeMobileBlockReason.lower(value) +} + + + +extension MobileBlockReason: Equatable, Hashable {} + + + +// Note that we don't yet support `indirect` for enums. +// See https://github.com/mozilla/uniffi-rs/issues/396 for further discussion. + +public enum MobileEntitlementState { + + case none + case trial + case active + case canceledValid + case canceledExpired + case expired +} + + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +public struct FfiConverterTypeMobileEntitlementState: FfiConverterRustBuffer { + typealias SwiftType = MobileEntitlementState + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> MobileEntitlementState { + let variant: Int32 = try readInt(&buf) + switch variant { + + case 1: return .none + + case 2: return .trial + + case 3: return .active + + case 4: return .canceledValid + + case 5: return .canceledExpired + + case 6: return .expired + + default: throw UniffiInternalError.unexpectedEnumCase + } + } + + public static func write(_ value: MobileEntitlementState, into buf: inout [UInt8]) { + switch value { + + + case .none: + writeInt(&buf, Int32(1)) + + + case .trial: + writeInt(&buf, Int32(2)) + + + case .active: + writeInt(&buf, Int32(3)) + + + case .canceledValid: + writeInt(&buf, Int32(4)) + + + case .canceledExpired: + writeInt(&buf, Int32(5)) + + + case .expired: + writeInt(&buf, Int32(6)) + + } + } +} + + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +public func FfiConverterTypeMobileEntitlementState_lift(_ buf: RustBuffer) throws -> MobileEntitlementState { + return try FfiConverterTypeMobileEntitlementState.lift(buf) +} + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +public func FfiConverterTypeMobileEntitlementState_lower(_ value: MobileEntitlementState) -> RustBuffer { + return FfiConverterTypeMobileEntitlementState.lower(value) +} + + + +extension MobileEntitlementState: Equatable, Hashable {} + + + +// Note that we don't yet support `indirect` for enums. +// See https://github.com/mozilla/uniffi-rs/issues/396 for further discussion. + +public enum MobileRealtimeEventType { + + case turnStarted + case audioCaptureCommitted + case responseStarted + case audioPlaybackStarted + case responseCompleted + case sessionError + case sessionReset +} + + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +public struct FfiConverterTypeMobileRealtimeEventType: FfiConverterRustBuffer { + typealias SwiftType = MobileRealtimeEventType + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> MobileRealtimeEventType { + let variant: Int32 = try readInt(&buf) + switch variant { + + case 1: return .turnStarted + + case 2: return .audioCaptureCommitted + + case 3: return .responseStarted + + case 4: return .audioPlaybackStarted + + case 5: return .responseCompleted + + case 6: return .sessionError + + case 7: return .sessionReset + + default: throw UniffiInternalError.unexpectedEnumCase + } + } + + public static func write(_ value: MobileRealtimeEventType, into buf: inout [UInt8]) { + switch value { + + + case .turnStarted: + writeInt(&buf, Int32(1)) + + + case .audioCaptureCommitted: + writeInt(&buf, Int32(2)) + + + case .responseStarted: + writeInt(&buf, Int32(3)) + + + case .audioPlaybackStarted: + writeInt(&buf, Int32(4)) + + + case .responseCompleted: + writeInt(&buf, Int32(5)) + + + case .sessionError: + writeInt(&buf, Int32(6)) + + + case .sessionReset: + writeInt(&buf, Int32(7)) + + } + } +} + + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +public func FfiConverterTypeMobileRealtimeEventType_lift(_ buf: RustBuffer) throws -> MobileRealtimeEventType { + return try FfiConverterTypeMobileRealtimeEventType.lift(buf) +} + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +public func FfiConverterTypeMobileRealtimeEventType_lower(_ value: MobileRealtimeEventType) -> RustBuffer { + return FfiConverterTypeMobileRealtimeEventType.lower(value) +} + + + +extension MobileRealtimeEventType: Equatable, Hashable {} + + + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +fileprivate struct FfiConverterOptionString: FfiConverterRustBuffer { + typealias SwiftType = String? + + public static func write(_ value: SwiftType, into buf: inout [UInt8]) { + guard let value = value else { + writeInt(&buf, Int8(0)) + return + } + writeInt(&buf, Int8(1)) + FfiConverterString.write(value, into: &buf) + } + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> SwiftType { + switch try readInt(&buf) as Int8 { + case 0: return nil + case 1: return try FfiConverterString.read(from: &buf) + default: throw UniffiInternalError.unexpectedOptionalTag + } + } +} + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +fileprivate struct FfiConverterOptionTypeMobileRealtimeReplaySummary: FfiConverterRustBuffer { + typealias SwiftType = MobileRealtimeReplaySummary? + + public static func write(_ value: SwiftType, into buf: inout [UInt8]) { + guard let value = value else { + writeInt(&buf, Int8(0)) + return + } + writeInt(&buf, Int8(1)) + FfiConverterTypeMobileRealtimeReplaySummary.write(value, into: &buf) + } + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> SwiftType { + switch try readInt(&buf) as Int8 { + case 0: return nil + case 1: return try FfiConverterTypeMobileRealtimeReplaySummary.read(from: &buf) + default: throw UniffiInternalError.unexpectedOptionalTag + } + } +} + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +fileprivate struct FfiConverterOptionTypeMobileBlockReason: FfiConverterRustBuffer { + typealias SwiftType = MobileBlockReason? + + public static func write(_ value: SwiftType, into buf: inout [UInt8]) { + guard let value = value else { + writeInt(&buf, Int8(0)) + return + } + writeInt(&buf, Int8(1)) + FfiConverterTypeMobileBlockReason.write(value, into: &buf) + } + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> SwiftType { + switch try readInt(&buf) as Int8 { + case 0: return nil + case 1: return try FfiConverterTypeMobileBlockReason.read(from: &buf) + default: throw UniffiInternalError.unexpectedOptionalTag + } + } +} + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +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 + } +} + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +fileprivate struct FfiConverterSequenceTypeMobileRealtimeEvent: FfiConverterRustBuffer { + typealias SwiftType = [MobileRealtimeEvent] + + public static func write(_ value: [MobileRealtimeEvent], into buf: inout [UInt8]) { + let len = Int32(value.count) + writeInt(&buf, len) + for item in value { + FfiConverterTypeMobileRealtimeEvent.write(item, into: &buf) + } + } + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> [MobileRealtimeEvent] { + let len: Int32 = try readInt(&buf) + var seq = [MobileRealtimeEvent]() + seq.reserveCapacity(Int(len)) + for _ in 0 ..< len { + seq.append(try FfiConverterTypeMobileRealtimeEvent.read(from: &buf)) + } + return seq + } +} +public func canStartTurnForMobile(input: MobilePolicyInput) -> MobilePolicyDecision { + return try! FfiConverterTypeMobilePolicyDecision.lift(try! rustCall() { + uniffi_skilly_core_mobile_sdk_fn_func_can_start_turn_for_mobile( + FfiConverterTypeMobilePolicyInput.lower(input),$0 + ) +}) +} +public func replayRealtimeEventsForMobile(events: [MobileRealtimeEvent]) -> MobileRealtimeReplaySummary? { + return try! FfiConverterOptionTypeMobileRealtimeReplaySummary.lift(try! rustCall() { + uniffi_skilly_core_mobile_sdk_fn_func_replay_realtime_events_for_mobile( + FfiConverterSequenceTypeMobileRealtimeEvent.lower(events),$0 + ) +}) +} +public func replayRealtimeEventsFromJsonForMobile(eventsJson: String) -> MobileRealtimeReplaySummary? { + return try! FfiConverterOptionTypeMobileRealtimeReplaySummary.lift(try! rustCall() { + uniffi_skilly_core_mobile_sdk_fn_func_replay_realtime_events_from_json_for_mobile( + FfiConverterString.lower(eventsJson),$0 + ) +}) +} +public func trialIsExhaustedForMobile(input: MobilePolicyInput) -> Bool { + return try! FfiConverterBool.lift(try! rustCall() { + uniffi_skilly_core_mobile_sdk_fn_func_trial_is_exhausted_for_mobile( + FfiConverterTypeMobilePolicyInput.lower(input),$0 + ) +}) +} +public func usageIsOverCapForMobile(input: MobilePolicyInput) -> Bool { + return try! FfiConverterBool.lift(try! rustCall() { + uniffi_skilly_core_mobile_sdk_fn_func_usage_is_over_cap_for_mobile( + FfiConverterTypeMobilePolicyInput.lower(input),$0 + ) +}) +} + +private enum InitializationResult { + case ok + case contractVersionMismatch + case apiChecksumMismatch +} +// Use a global variable 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 = 26 + // Get the scaffolding contract version by calling the into the dylib + let scaffolding_contract_version = ffi_skilly_core_mobile_sdk_uniffi_contract_version() + if bindings_contract_version != scaffolding_contract_version { + return InitializationResult.contractVersionMismatch + } + if (uniffi_skilly_core_mobile_sdk_checksum_func_can_start_turn_for_mobile() != 55318) { + return InitializationResult.apiChecksumMismatch + } + if (uniffi_skilly_core_mobile_sdk_checksum_func_replay_realtime_events_for_mobile() != 3997) { + return InitializationResult.apiChecksumMismatch + } + if (uniffi_skilly_core_mobile_sdk_checksum_func_replay_realtime_events_from_json_for_mobile() != 42033) { + return InitializationResult.apiChecksumMismatch + } + if (uniffi_skilly_core_mobile_sdk_checksum_func_trial_is_exhausted_for_mobile() != 1523) { + return InitializationResult.apiChecksumMismatch + } + if (uniffi_skilly_core_mobile_sdk_checksum_func_usage_is_over_cap_for_mobile() != 40273) { + return InitializationResult.apiChecksumMismatch + } + + 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") + } +} + +// swiftlint:enable all \ No newline at end of file diff --git a/sdk/ios/generated/skilly_core_mobile_sdkFFI.h b/sdk/ios/generated/skilly_core_mobile_sdkFFI.h new file mode 100644 index 00000000..2c84596a --- /dev/null +++ b/sdk/ios/generated/skilly_core_mobile_sdkFFI.h @@ -0,0 +1,595 @@ +// 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 +#include +#include + +// 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 +{ + uint64_t capacity; + uint64_t len; + uint8_t *_Nullable data; +} RustBuffer; + +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 +#ifndef UNIFFI_FFIDEF_RUST_FUTURE_CONTINUATION_CALLBACK +#define UNIFFI_FFIDEF_RUST_FUTURE_CONTINUATION_CALLBACK +typedef void (*UniffiRustFutureContinuationCallback)(uint64_t, int8_t + ); + +#endif +#ifndef UNIFFI_FFIDEF_FOREIGN_FUTURE_FREE +#define UNIFFI_FFIDEF_FOREIGN_FUTURE_FREE +typedef void (*UniffiForeignFutureFree)(uint64_t + ); + +#endif +#ifndef UNIFFI_FFIDEF_CALLBACK_INTERFACE_FREE +#define UNIFFI_FFIDEF_CALLBACK_INTERFACE_FREE +typedef void (*UniffiCallbackInterfaceFree)(uint64_t + ); + +#endif +#ifndef UNIFFI_FFIDEF_FOREIGN_FUTURE +#define UNIFFI_FFIDEF_FOREIGN_FUTURE +typedef struct UniffiForeignFuture { + uint64_t handle; + UniffiForeignFutureFree _Nonnull free; +} UniffiForeignFuture; + +#endif +#ifndef UNIFFI_FFIDEF_FOREIGN_FUTURE_STRUCT_U8 +#define UNIFFI_FFIDEF_FOREIGN_FUTURE_STRUCT_U8 +typedef struct UniffiForeignFutureStructU8 { + uint8_t returnValue; + RustCallStatus callStatus; +} UniffiForeignFutureStructU8; + +#endif +#ifndef UNIFFI_FFIDEF_FOREIGN_FUTURE_COMPLETE_U8 +#define UNIFFI_FFIDEF_FOREIGN_FUTURE_COMPLETE_U8 +typedef void (*UniffiForeignFutureCompleteU8)(uint64_t, UniffiForeignFutureStructU8 + ); + +#endif +#ifndef UNIFFI_FFIDEF_FOREIGN_FUTURE_STRUCT_I8 +#define UNIFFI_FFIDEF_FOREIGN_FUTURE_STRUCT_I8 +typedef struct UniffiForeignFutureStructI8 { + int8_t returnValue; + RustCallStatus callStatus; +} UniffiForeignFutureStructI8; + +#endif +#ifndef UNIFFI_FFIDEF_FOREIGN_FUTURE_COMPLETE_I8 +#define UNIFFI_FFIDEF_FOREIGN_FUTURE_COMPLETE_I8 +typedef void (*UniffiForeignFutureCompleteI8)(uint64_t, UniffiForeignFutureStructI8 + ); + +#endif +#ifndef UNIFFI_FFIDEF_FOREIGN_FUTURE_STRUCT_U16 +#define UNIFFI_FFIDEF_FOREIGN_FUTURE_STRUCT_U16 +typedef struct UniffiForeignFutureStructU16 { + uint16_t returnValue; + RustCallStatus callStatus; +} UniffiForeignFutureStructU16; + +#endif +#ifndef UNIFFI_FFIDEF_FOREIGN_FUTURE_COMPLETE_U16 +#define UNIFFI_FFIDEF_FOREIGN_FUTURE_COMPLETE_U16 +typedef void (*UniffiForeignFutureCompleteU16)(uint64_t, UniffiForeignFutureStructU16 + ); + +#endif +#ifndef UNIFFI_FFIDEF_FOREIGN_FUTURE_STRUCT_I16 +#define UNIFFI_FFIDEF_FOREIGN_FUTURE_STRUCT_I16 +typedef struct UniffiForeignFutureStructI16 { + int16_t returnValue; + RustCallStatus callStatus; +} UniffiForeignFutureStructI16; + +#endif +#ifndef UNIFFI_FFIDEF_FOREIGN_FUTURE_COMPLETE_I16 +#define UNIFFI_FFIDEF_FOREIGN_FUTURE_COMPLETE_I16 +typedef void (*UniffiForeignFutureCompleteI16)(uint64_t, UniffiForeignFutureStructI16 + ); + +#endif +#ifndef UNIFFI_FFIDEF_FOREIGN_FUTURE_STRUCT_U32 +#define UNIFFI_FFIDEF_FOREIGN_FUTURE_STRUCT_U32 +typedef struct UniffiForeignFutureStructU32 { + uint32_t returnValue; + RustCallStatus callStatus; +} UniffiForeignFutureStructU32; + +#endif +#ifndef UNIFFI_FFIDEF_FOREIGN_FUTURE_COMPLETE_U32 +#define UNIFFI_FFIDEF_FOREIGN_FUTURE_COMPLETE_U32 +typedef void (*UniffiForeignFutureCompleteU32)(uint64_t, UniffiForeignFutureStructU32 + ); + +#endif +#ifndef UNIFFI_FFIDEF_FOREIGN_FUTURE_STRUCT_I32 +#define UNIFFI_FFIDEF_FOREIGN_FUTURE_STRUCT_I32 +typedef struct UniffiForeignFutureStructI32 { + int32_t returnValue; + RustCallStatus callStatus; +} UniffiForeignFutureStructI32; + +#endif +#ifndef UNIFFI_FFIDEF_FOREIGN_FUTURE_COMPLETE_I32 +#define UNIFFI_FFIDEF_FOREIGN_FUTURE_COMPLETE_I32 +typedef void (*UniffiForeignFutureCompleteI32)(uint64_t, UniffiForeignFutureStructI32 + ); + +#endif +#ifndef UNIFFI_FFIDEF_FOREIGN_FUTURE_STRUCT_U64 +#define UNIFFI_FFIDEF_FOREIGN_FUTURE_STRUCT_U64 +typedef struct UniffiForeignFutureStructU64 { + uint64_t returnValue; + RustCallStatus callStatus; +} UniffiForeignFutureStructU64; + +#endif +#ifndef UNIFFI_FFIDEF_FOREIGN_FUTURE_COMPLETE_U64 +#define UNIFFI_FFIDEF_FOREIGN_FUTURE_COMPLETE_U64 +typedef void (*UniffiForeignFutureCompleteU64)(uint64_t, UniffiForeignFutureStructU64 + ); + +#endif +#ifndef UNIFFI_FFIDEF_FOREIGN_FUTURE_STRUCT_I64 +#define UNIFFI_FFIDEF_FOREIGN_FUTURE_STRUCT_I64 +typedef struct UniffiForeignFutureStructI64 { + int64_t returnValue; + RustCallStatus callStatus; +} UniffiForeignFutureStructI64; + +#endif +#ifndef UNIFFI_FFIDEF_FOREIGN_FUTURE_COMPLETE_I64 +#define UNIFFI_FFIDEF_FOREIGN_FUTURE_COMPLETE_I64 +typedef void (*UniffiForeignFutureCompleteI64)(uint64_t, UniffiForeignFutureStructI64 + ); + +#endif +#ifndef UNIFFI_FFIDEF_FOREIGN_FUTURE_STRUCT_F32 +#define UNIFFI_FFIDEF_FOREIGN_FUTURE_STRUCT_F32 +typedef struct UniffiForeignFutureStructF32 { + float returnValue; + RustCallStatus callStatus; +} UniffiForeignFutureStructF32; + +#endif +#ifndef UNIFFI_FFIDEF_FOREIGN_FUTURE_COMPLETE_F32 +#define UNIFFI_FFIDEF_FOREIGN_FUTURE_COMPLETE_F32 +typedef void (*UniffiForeignFutureCompleteF32)(uint64_t, UniffiForeignFutureStructF32 + ); + +#endif +#ifndef UNIFFI_FFIDEF_FOREIGN_FUTURE_STRUCT_F64 +#define UNIFFI_FFIDEF_FOREIGN_FUTURE_STRUCT_F64 +typedef struct UniffiForeignFutureStructF64 { + double returnValue; + RustCallStatus callStatus; +} UniffiForeignFutureStructF64; + +#endif +#ifndef UNIFFI_FFIDEF_FOREIGN_FUTURE_COMPLETE_F64 +#define UNIFFI_FFIDEF_FOREIGN_FUTURE_COMPLETE_F64 +typedef void (*UniffiForeignFutureCompleteF64)(uint64_t, UniffiForeignFutureStructF64 + ); + +#endif +#ifndef UNIFFI_FFIDEF_FOREIGN_FUTURE_STRUCT_POINTER +#define UNIFFI_FFIDEF_FOREIGN_FUTURE_STRUCT_POINTER +typedef struct UniffiForeignFutureStructPointer { + void*_Nonnull returnValue; + RustCallStatus callStatus; +} UniffiForeignFutureStructPointer; + +#endif +#ifndef UNIFFI_FFIDEF_FOREIGN_FUTURE_COMPLETE_POINTER +#define UNIFFI_FFIDEF_FOREIGN_FUTURE_COMPLETE_POINTER +typedef void (*UniffiForeignFutureCompletePointer)(uint64_t, UniffiForeignFutureStructPointer + ); + +#endif +#ifndef UNIFFI_FFIDEF_FOREIGN_FUTURE_STRUCT_RUST_BUFFER +#define UNIFFI_FFIDEF_FOREIGN_FUTURE_STRUCT_RUST_BUFFER +typedef struct UniffiForeignFutureStructRustBuffer { + RustBuffer returnValue; + RustCallStatus callStatus; +} UniffiForeignFutureStructRustBuffer; + +#endif +#ifndef UNIFFI_FFIDEF_FOREIGN_FUTURE_COMPLETE_RUST_BUFFER +#define UNIFFI_FFIDEF_FOREIGN_FUTURE_COMPLETE_RUST_BUFFER +typedef void (*UniffiForeignFutureCompleteRustBuffer)(uint64_t, UniffiForeignFutureStructRustBuffer + ); + +#endif +#ifndef UNIFFI_FFIDEF_FOREIGN_FUTURE_STRUCT_VOID +#define UNIFFI_FFIDEF_FOREIGN_FUTURE_STRUCT_VOID +typedef struct UniffiForeignFutureStructVoid { + RustCallStatus callStatus; +} UniffiForeignFutureStructVoid; + +#endif +#ifndef UNIFFI_FFIDEF_FOREIGN_FUTURE_COMPLETE_VOID +#define UNIFFI_FFIDEF_FOREIGN_FUTURE_COMPLETE_VOID +typedef void (*UniffiForeignFutureCompleteVoid)(uint64_t, UniffiForeignFutureStructVoid + ); + +#endif +#ifndef UNIFFI_FFIDEF_UNIFFI_SKILLY_CORE_MOBILE_SDK_FN_FUNC_CAN_START_TURN_FOR_MOBILE +#define UNIFFI_FFIDEF_UNIFFI_SKILLY_CORE_MOBILE_SDK_FN_FUNC_CAN_START_TURN_FOR_MOBILE +RustBuffer uniffi_skilly_core_mobile_sdk_fn_func_can_start_turn_for_mobile(RustBuffer input, RustCallStatus *_Nonnull out_status +); +#endif +#ifndef UNIFFI_FFIDEF_UNIFFI_SKILLY_CORE_MOBILE_SDK_FN_FUNC_REPLAY_REALTIME_EVENTS_FOR_MOBILE +#define UNIFFI_FFIDEF_UNIFFI_SKILLY_CORE_MOBILE_SDK_FN_FUNC_REPLAY_REALTIME_EVENTS_FOR_MOBILE +RustBuffer uniffi_skilly_core_mobile_sdk_fn_func_replay_realtime_events_for_mobile(RustBuffer events, RustCallStatus *_Nonnull out_status +); +#endif +#ifndef UNIFFI_FFIDEF_UNIFFI_SKILLY_CORE_MOBILE_SDK_FN_FUNC_REPLAY_REALTIME_EVENTS_FROM_JSON_FOR_MOBILE +#define UNIFFI_FFIDEF_UNIFFI_SKILLY_CORE_MOBILE_SDK_FN_FUNC_REPLAY_REALTIME_EVENTS_FROM_JSON_FOR_MOBILE +RustBuffer uniffi_skilly_core_mobile_sdk_fn_func_replay_realtime_events_from_json_for_mobile(RustBuffer events_json, RustCallStatus *_Nonnull out_status +); +#endif +#ifndef UNIFFI_FFIDEF_UNIFFI_SKILLY_CORE_MOBILE_SDK_FN_FUNC_TRIAL_IS_EXHAUSTED_FOR_MOBILE +#define UNIFFI_FFIDEF_UNIFFI_SKILLY_CORE_MOBILE_SDK_FN_FUNC_TRIAL_IS_EXHAUSTED_FOR_MOBILE +int8_t uniffi_skilly_core_mobile_sdk_fn_func_trial_is_exhausted_for_mobile(RustBuffer input, RustCallStatus *_Nonnull out_status +); +#endif +#ifndef UNIFFI_FFIDEF_UNIFFI_SKILLY_CORE_MOBILE_SDK_FN_FUNC_USAGE_IS_OVER_CAP_FOR_MOBILE +#define UNIFFI_FFIDEF_UNIFFI_SKILLY_CORE_MOBILE_SDK_FN_FUNC_USAGE_IS_OVER_CAP_FOR_MOBILE +int8_t uniffi_skilly_core_mobile_sdk_fn_func_usage_is_over_cap_for_mobile(RustBuffer input, RustCallStatus *_Nonnull out_status +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUSTBUFFER_ALLOC +#define UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUSTBUFFER_ALLOC +RustBuffer ffi_skilly_core_mobile_sdk_rustbuffer_alloc(uint64_t size, RustCallStatus *_Nonnull out_status +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUSTBUFFER_FROM_BYTES +#define UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUSTBUFFER_FROM_BYTES +RustBuffer ffi_skilly_core_mobile_sdk_rustbuffer_from_bytes(ForeignBytes bytes, RustCallStatus *_Nonnull out_status +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUSTBUFFER_FREE +#define UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUSTBUFFER_FREE +void ffi_skilly_core_mobile_sdk_rustbuffer_free(RustBuffer buf, RustCallStatus *_Nonnull out_status +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUSTBUFFER_RESERVE +#define UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUSTBUFFER_RESERVE +RustBuffer ffi_skilly_core_mobile_sdk_rustbuffer_reserve(RustBuffer buf, uint64_t additional, RustCallStatus *_Nonnull out_status +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_POLL_U8 +#define UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_POLL_U8 +void ffi_skilly_core_mobile_sdk_rust_future_poll_u8(uint64_t handle, UniffiRustFutureContinuationCallback _Nonnull callback, uint64_t callback_data +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_CANCEL_U8 +#define UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_CANCEL_U8 +void ffi_skilly_core_mobile_sdk_rust_future_cancel_u8(uint64_t handle +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_FREE_U8 +#define UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_FREE_U8 +void ffi_skilly_core_mobile_sdk_rust_future_free_u8(uint64_t handle +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_COMPLETE_U8 +#define UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_COMPLETE_U8 +uint8_t ffi_skilly_core_mobile_sdk_rust_future_complete_u8(uint64_t handle, RustCallStatus *_Nonnull out_status +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_POLL_I8 +#define UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_POLL_I8 +void ffi_skilly_core_mobile_sdk_rust_future_poll_i8(uint64_t handle, UniffiRustFutureContinuationCallback _Nonnull callback, uint64_t callback_data +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_CANCEL_I8 +#define UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_CANCEL_I8 +void ffi_skilly_core_mobile_sdk_rust_future_cancel_i8(uint64_t handle +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_FREE_I8 +#define UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_FREE_I8 +void ffi_skilly_core_mobile_sdk_rust_future_free_i8(uint64_t handle +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_COMPLETE_I8 +#define UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_COMPLETE_I8 +int8_t ffi_skilly_core_mobile_sdk_rust_future_complete_i8(uint64_t handle, RustCallStatus *_Nonnull out_status +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_POLL_U16 +#define UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_POLL_U16 +void ffi_skilly_core_mobile_sdk_rust_future_poll_u16(uint64_t handle, UniffiRustFutureContinuationCallback _Nonnull callback, uint64_t callback_data +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_CANCEL_U16 +#define UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_CANCEL_U16 +void ffi_skilly_core_mobile_sdk_rust_future_cancel_u16(uint64_t handle +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_FREE_U16 +#define UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_FREE_U16 +void ffi_skilly_core_mobile_sdk_rust_future_free_u16(uint64_t handle +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_COMPLETE_U16 +#define UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_COMPLETE_U16 +uint16_t ffi_skilly_core_mobile_sdk_rust_future_complete_u16(uint64_t handle, RustCallStatus *_Nonnull out_status +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_POLL_I16 +#define UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_POLL_I16 +void ffi_skilly_core_mobile_sdk_rust_future_poll_i16(uint64_t handle, UniffiRustFutureContinuationCallback _Nonnull callback, uint64_t callback_data +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_CANCEL_I16 +#define UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_CANCEL_I16 +void ffi_skilly_core_mobile_sdk_rust_future_cancel_i16(uint64_t handle +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_FREE_I16 +#define UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_FREE_I16 +void ffi_skilly_core_mobile_sdk_rust_future_free_i16(uint64_t handle +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_COMPLETE_I16 +#define UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_COMPLETE_I16 +int16_t ffi_skilly_core_mobile_sdk_rust_future_complete_i16(uint64_t handle, RustCallStatus *_Nonnull out_status +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_POLL_U32 +#define UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_POLL_U32 +void ffi_skilly_core_mobile_sdk_rust_future_poll_u32(uint64_t handle, UniffiRustFutureContinuationCallback _Nonnull callback, uint64_t callback_data +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_CANCEL_U32 +#define UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_CANCEL_U32 +void ffi_skilly_core_mobile_sdk_rust_future_cancel_u32(uint64_t handle +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_FREE_U32 +#define UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_FREE_U32 +void ffi_skilly_core_mobile_sdk_rust_future_free_u32(uint64_t handle +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_COMPLETE_U32 +#define UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_COMPLETE_U32 +uint32_t ffi_skilly_core_mobile_sdk_rust_future_complete_u32(uint64_t handle, RustCallStatus *_Nonnull out_status +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_POLL_I32 +#define UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_POLL_I32 +void ffi_skilly_core_mobile_sdk_rust_future_poll_i32(uint64_t handle, UniffiRustFutureContinuationCallback _Nonnull callback, uint64_t callback_data +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_CANCEL_I32 +#define UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_CANCEL_I32 +void ffi_skilly_core_mobile_sdk_rust_future_cancel_i32(uint64_t handle +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_FREE_I32 +#define UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_FREE_I32 +void ffi_skilly_core_mobile_sdk_rust_future_free_i32(uint64_t handle +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_COMPLETE_I32 +#define UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_COMPLETE_I32 +int32_t ffi_skilly_core_mobile_sdk_rust_future_complete_i32(uint64_t handle, RustCallStatus *_Nonnull out_status +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_POLL_U64 +#define UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_POLL_U64 +void ffi_skilly_core_mobile_sdk_rust_future_poll_u64(uint64_t handle, UniffiRustFutureContinuationCallback _Nonnull callback, uint64_t callback_data +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_CANCEL_U64 +#define UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_CANCEL_U64 +void ffi_skilly_core_mobile_sdk_rust_future_cancel_u64(uint64_t handle +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_FREE_U64 +#define UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_FREE_U64 +void ffi_skilly_core_mobile_sdk_rust_future_free_u64(uint64_t handle +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_COMPLETE_U64 +#define UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_COMPLETE_U64 +uint64_t ffi_skilly_core_mobile_sdk_rust_future_complete_u64(uint64_t handle, RustCallStatus *_Nonnull out_status +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_POLL_I64 +#define UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_POLL_I64 +void ffi_skilly_core_mobile_sdk_rust_future_poll_i64(uint64_t handle, UniffiRustFutureContinuationCallback _Nonnull callback, uint64_t callback_data +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_CANCEL_I64 +#define UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_CANCEL_I64 +void ffi_skilly_core_mobile_sdk_rust_future_cancel_i64(uint64_t handle +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_FREE_I64 +#define UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_FREE_I64 +void ffi_skilly_core_mobile_sdk_rust_future_free_i64(uint64_t handle +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_COMPLETE_I64 +#define UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_COMPLETE_I64 +int64_t ffi_skilly_core_mobile_sdk_rust_future_complete_i64(uint64_t handle, RustCallStatus *_Nonnull out_status +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_POLL_F32 +#define UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_POLL_F32 +void ffi_skilly_core_mobile_sdk_rust_future_poll_f32(uint64_t handle, UniffiRustFutureContinuationCallback _Nonnull callback, uint64_t callback_data +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_CANCEL_F32 +#define UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_CANCEL_F32 +void ffi_skilly_core_mobile_sdk_rust_future_cancel_f32(uint64_t handle +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_FREE_F32 +#define UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_FREE_F32 +void ffi_skilly_core_mobile_sdk_rust_future_free_f32(uint64_t handle +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_COMPLETE_F32 +#define UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_COMPLETE_F32 +float ffi_skilly_core_mobile_sdk_rust_future_complete_f32(uint64_t handle, RustCallStatus *_Nonnull out_status +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_POLL_F64 +#define UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_POLL_F64 +void ffi_skilly_core_mobile_sdk_rust_future_poll_f64(uint64_t handle, UniffiRustFutureContinuationCallback _Nonnull callback, uint64_t callback_data +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_CANCEL_F64 +#define UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_CANCEL_F64 +void ffi_skilly_core_mobile_sdk_rust_future_cancel_f64(uint64_t handle +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_FREE_F64 +#define UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_FREE_F64 +void ffi_skilly_core_mobile_sdk_rust_future_free_f64(uint64_t handle +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_COMPLETE_F64 +#define UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_COMPLETE_F64 +double ffi_skilly_core_mobile_sdk_rust_future_complete_f64(uint64_t handle, RustCallStatus *_Nonnull out_status +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_POLL_POINTER +#define UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_POLL_POINTER +void ffi_skilly_core_mobile_sdk_rust_future_poll_pointer(uint64_t handle, UniffiRustFutureContinuationCallback _Nonnull callback, uint64_t callback_data +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_CANCEL_POINTER +#define UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_CANCEL_POINTER +void ffi_skilly_core_mobile_sdk_rust_future_cancel_pointer(uint64_t handle +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_FREE_POINTER +#define UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_FREE_POINTER +void ffi_skilly_core_mobile_sdk_rust_future_free_pointer(uint64_t handle +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_COMPLETE_POINTER +#define UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_COMPLETE_POINTER +void*_Nonnull ffi_skilly_core_mobile_sdk_rust_future_complete_pointer(uint64_t handle, RustCallStatus *_Nonnull out_status +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_POLL_RUST_BUFFER +#define UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_POLL_RUST_BUFFER +void ffi_skilly_core_mobile_sdk_rust_future_poll_rust_buffer(uint64_t handle, UniffiRustFutureContinuationCallback _Nonnull callback, uint64_t callback_data +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_CANCEL_RUST_BUFFER +#define UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_CANCEL_RUST_BUFFER +void ffi_skilly_core_mobile_sdk_rust_future_cancel_rust_buffer(uint64_t handle +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_FREE_RUST_BUFFER +#define UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_FREE_RUST_BUFFER +void ffi_skilly_core_mobile_sdk_rust_future_free_rust_buffer(uint64_t handle +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_COMPLETE_RUST_BUFFER +#define UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_COMPLETE_RUST_BUFFER +RustBuffer ffi_skilly_core_mobile_sdk_rust_future_complete_rust_buffer(uint64_t handle, RustCallStatus *_Nonnull out_status +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_POLL_VOID +#define UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_POLL_VOID +void ffi_skilly_core_mobile_sdk_rust_future_poll_void(uint64_t handle, UniffiRustFutureContinuationCallback _Nonnull callback, uint64_t callback_data +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_CANCEL_VOID +#define UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_CANCEL_VOID +void ffi_skilly_core_mobile_sdk_rust_future_cancel_void(uint64_t handle +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_FREE_VOID +#define UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_FREE_VOID +void ffi_skilly_core_mobile_sdk_rust_future_free_void(uint64_t handle +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_COMPLETE_VOID +#define UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_RUST_FUTURE_COMPLETE_VOID +void ffi_skilly_core_mobile_sdk_rust_future_complete_void(uint64_t handle, RustCallStatus *_Nonnull out_status +); +#endif +#ifndef UNIFFI_FFIDEF_UNIFFI_SKILLY_CORE_MOBILE_SDK_CHECKSUM_FUNC_CAN_START_TURN_FOR_MOBILE +#define UNIFFI_FFIDEF_UNIFFI_SKILLY_CORE_MOBILE_SDK_CHECKSUM_FUNC_CAN_START_TURN_FOR_MOBILE +uint16_t uniffi_skilly_core_mobile_sdk_checksum_func_can_start_turn_for_mobile(void + +); +#endif +#ifndef UNIFFI_FFIDEF_UNIFFI_SKILLY_CORE_MOBILE_SDK_CHECKSUM_FUNC_REPLAY_REALTIME_EVENTS_FOR_MOBILE +#define UNIFFI_FFIDEF_UNIFFI_SKILLY_CORE_MOBILE_SDK_CHECKSUM_FUNC_REPLAY_REALTIME_EVENTS_FOR_MOBILE +uint16_t uniffi_skilly_core_mobile_sdk_checksum_func_replay_realtime_events_for_mobile(void + +); +#endif +#ifndef UNIFFI_FFIDEF_UNIFFI_SKILLY_CORE_MOBILE_SDK_CHECKSUM_FUNC_REPLAY_REALTIME_EVENTS_FROM_JSON_FOR_MOBILE +#define UNIFFI_FFIDEF_UNIFFI_SKILLY_CORE_MOBILE_SDK_CHECKSUM_FUNC_REPLAY_REALTIME_EVENTS_FROM_JSON_FOR_MOBILE +uint16_t uniffi_skilly_core_mobile_sdk_checksum_func_replay_realtime_events_from_json_for_mobile(void + +); +#endif +#ifndef UNIFFI_FFIDEF_UNIFFI_SKILLY_CORE_MOBILE_SDK_CHECKSUM_FUNC_TRIAL_IS_EXHAUSTED_FOR_MOBILE +#define UNIFFI_FFIDEF_UNIFFI_SKILLY_CORE_MOBILE_SDK_CHECKSUM_FUNC_TRIAL_IS_EXHAUSTED_FOR_MOBILE +uint16_t uniffi_skilly_core_mobile_sdk_checksum_func_trial_is_exhausted_for_mobile(void + +); +#endif +#ifndef UNIFFI_FFIDEF_UNIFFI_SKILLY_CORE_MOBILE_SDK_CHECKSUM_FUNC_USAGE_IS_OVER_CAP_FOR_MOBILE +#define UNIFFI_FFIDEF_UNIFFI_SKILLY_CORE_MOBILE_SDK_CHECKSUM_FUNC_USAGE_IS_OVER_CAP_FOR_MOBILE +uint16_t uniffi_skilly_core_mobile_sdk_checksum_func_usage_is_over_cap_for_mobile(void + +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_UNIFFI_CONTRACT_VERSION +#define UNIFFI_FFIDEF_FFI_SKILLY_CORE_MOBILE_SDK_UNIFFI_CONTRACT_VERSION +uint32_t ffi_skilly_core_mobile_sdk_uniffi_contract_version(void + +); +#endif + diff --git a/sdk/ios/generated/skilly_core_mobile_sdkFFI.modulemap b/sdk/ios/generated/skilly_core_mobile_sdkFFI.modulemap new file mode 100644 index 00000000..926bc4d4 --- /dev/null +++ b/sdk/ios/generated/skilly_core_mobile_sdkFFI.modulemap @@ -0,0 +1,4 @@ +module skilly_core_mobile_sdkFFI { + header "skilly_core_mobile_sdkFFI.h" + export * +} \ No newline at end of file diff --git a/sdk/ios/sample/PolicyAndRealtimeExample.swift b/sdk/ios/sample/PolicyAndRealtimeExample.swift new file mode 100644 index 00000000..b386cc12 --- /dev/null +++ b/sdk/ios/sample/PolicyAndRealtimeExample.swift @@ -0,0 +1,29 @@ +import Foundation + +// This sample assumes the generated UniFFI Swift files from sdk/ios/generated +// are included in your target. +func runPolicyAndRealtimeDemo() { + let policyInput = MobilePolicyInput( + userId: "ios-user-123", + entitlementState: .trial, + trialSecondsUsed: 400, + usageSecondsUsed: 0, + adminWorkosUserIds: [] + ) + + let policyDecision = canStartTurnForMobile(input: policyInput) + print("Allowed: \(policyDecision.allowed), reason: \(String(describing: policyDecision.reason))") + + let events = [ + MobileRealtimeEvent(eventType: .turnStarted, turnId: "turn-ios-1", message: nil), + MobileRealtimeEvent(eventType: .audioCaptureCommitted, turnId: "turn-ios-1", message: nil), + MobileRealtimeEvent(eventType: .responseStarted, turnId: "turn-ios-1", message: nil), + MobileRealtimeEvent(eventType: .responseCompleted, turnId: "turn-ios-1", message: nil), + ] + + if let summary = replayRealtimeEventsForMobile(events: events) { + print("Phase: \(summary.phaseName), turns completed: \(summary.turnsCompleted)") + } else { + print("Replay failed.") + } +}