diff --git a/Cargo.lock b/Cargo.lock index cd3cb1af5..ae241214a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -277,6 +277,48 @@ dependencies = [ "libloading", ] +[[package]] +name = "askama" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d4744ed2eef2645831b441d8f5459689ade2ab27c854488fbab1fbe94fce1a7" +dependencies = [ + "askama_derive", + "itoa", + "percent-encoding", + "serde", + "serde_json", +] + +[[package]] +name = "askama_derive" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d661e0f57be36a5c14c48f78d09011e67e0cb618f269cca9f2fd8d15b68c46ac" +dependencies = [ + "askama_parser", + "basic-toml", + "memchr", + "proc-macro2", + "quote", + "rustc-hash 2.1.1", + "serde", + "serde_derive", + "syn 2.0.106", +] + +[[package]] +name = "askama_parser" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf315ce6524c857bb129ff794935cf6d42c82a6cff60526fe2a63593de4d0d4f" +dependencies = [ + "memchr", + "serde", + "serde_derive", + "winnow", +] + [[package]] name = "async-channel" version = "1.9.0" @@ -518,6 +560,15 @@ version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55248b47b0caf0546f7988906588779981c43bb1bc9d0c44087278f80cdb44ba" +[[package]] +name = "basic-toml" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba62675e8242a4c4e806d12f11d136e626e6c8361d6b829310732241652a178a" +dependencies = [ + "serde", +] + [[package]] name = "basic_room" version = "0.1.0" @@ -744,6 +795,38 @@ dependencies = [ "wayland-client", ] +[[package]] +name = "camino" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "276a59bf2b2c967788139340c9f0c5b12d7fd6630315c15c217e559de85d2609" +dependencies = [ + "serde_core", +] + +[[package]] +name = "cargo-platform" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e35af189006b9c0f00a064685c727031e3ed2d8020f7ba284d78cc2671bd36ea" +dependencies = [ + "serde", +] + +[[package]] +name = "cargo_metadata" +version = "0.19.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd5eb614ed4c27c5d706420e4320fbe3216ab31fa1c33cd8246ac36dae4479ba" +dependencies = [ + "camino", + "cargo-platform", + "semver", + "serde", + "serde_json", + "thiserror 2.0.17", +] + [[package]] name = "castaway" version = "0.1.2" @@ -1758,6 +1841,15 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "fs-err" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88a41f105fe1d5b6b34b2055e3dc59bb79b46b48b2040b9e6c7b4b5de097aa41" +dependencies = [ + "autocfg", +] + [[package]] name = "fs2" version = "0.4.3" @@ -1998,6 +2090,17 @@ dependencies = [ "gl_generator", ] +[[package]] +name = "goblin" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b363a30c165f666402fe6a3024d3bec7ebc898f96a4a23bd1c99f8dbf3f4f47" +dependencies = [ + "log", + "plain", + "scroll", +] + [[package]] name = "gpu-alloc" version = "0.6.0" @@ -2545,6 +2648,8 @@ checksum = "4b0f83760fb341a774ed326568e19f5a863af4a952def8c39f9ab92fd95b88e5" dependencies = [ "equivalent", "hashbrown 0.16.0", + "serde", + "serde_core", ] [[package]] @@ -3016,6 +3121,18 @@ dependencies = [ "tokio-stream", ] +[[package]] +name = "livekit-uniffi" +version = "0.1.0" +dependencies = [ + "livekit-api", + "livekit-protocol", + "log", + "once_cell", + "tokio", + "uniffi", +] + [[package]] name = "local_audio" version = "0.1.0" @@ -3948,6 +4065,12 @@ version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" +[[package]] +name = "plain" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" + [[package]] name = "play_from_disk" version = "0.1.0" @@ -4760,6 +4883,26 @@ version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d68f2ec51b097e4c1a75b681a8bec621909b5e91f15bb7b840c4f2f7b01148b2" +[[package]] +name = "scroll" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ab8598aa408498679922eff7fa985c25d58a90771bd6be794434c5277eab1a6" +dependencies = [ + "scroll_derive", +] + +[[package]] +name = "scroll_derive" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1783eabc414609e28a5ba76aee5ddd52199f7107a0b24c2e9746a1ecc34a683d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", +] + [[package]] name = "sct" version = "0.7.1" @@ -4824,6 +4967,10 @@ name = "semver" version = "1.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" +dependencies = [ + "serde", + "serde_core", +] [[package]] name = "send_bytes" @@ -4881,6 +5028,15 @@ dependencies = [ "serde_core", ] +[[package]] +name = "serde_spanned" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e24345aa0fe688594e73770a5f6d1b216508b4f93484c0026d521acd30134392" +dependencies = [ + "serde_core", +] + [[package]] name = "serde_urlencoded" version = "0.7.1" @@ -4945,6 +5101,12 @@ version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" +[[package]] +name = "siphasher" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" + [[package]] name = "slab" version = "0.4.11" @@ -4977,6 +5139,12 @@ version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" +[[package]] +name = "smawk" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7c388c1b5e93756d0c740965c41e8822f866621d41acbdf6336a6a168f8840c" + [[package]] name = "smithay-client-toolkit" version = "0.19.2" @@ -5203,6 +5371,15 @@ dependencies = [ "syn 2.0.106", ] +[[package]] +name = "textwrap" +version = "0.16.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c13547615a44dc9c452a8a534638acdf07120d4b6847c8178705da06306a3057" +dependencies = [ + "smawk", +] + [[package]] name = "thiserror" version = "1.0.69" @@ -5457,6 +5634,21 @@ dependencies = [ "tokio", ] +[[package]] +name = "toml" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0dc8b1fb61449e27716ec0e1bdf0f6b8f3e8f6b05391e8497b8b6d7804ea6d8" +dependencies = [ + "indexmap 2.11.4", + "serde_core", + "serde_spanned", + "toml_datetime", + "toml_parser", + "toml_writer", + "winnow", +] + [[package]] name = "toml_datetime" version = "0.7.3" @@ -5487,6 +5679,12 @@ dependencies = [ "winnow", ] +[[package]] +name = "toml_writer" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df8b2b54733674ad286d16267dcfc7a71ed5c776e4ac7aa3c3e2561f7c637bf2" + [[package]] name = "tonic" version = "0.9.2" @@ -5750,6 +5948,139 @@ version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" +[[package]] +name = "uniffi" +version = "0.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c866f627c3f04c3df068b68bb2d725492caaa539dd313e2a9d26bb85b1a32f4e" +dependencies = [ + "anyhow", + "camino", + "cargo_metadata", + "clap", + "uniffi_bindgen", + "uniffi_build", + "uniffi_core", + "uniffi_macros", + "uniffi_pipeline", +] + +[[package]] +name = "uniffi_bindgen" +version = "0.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c8ca600167641ebe7c8ba9254af40492dda3397c528cc3b2f511bd23e8541a5" +dependencies = [ + "anyhow", + "askama", + "camino", + "cargo_metadata", + "fs-err", + "glob", + "goblin", + "heck 0.5.0", + "indexmap 2.11.4", + "once_cell", + "serde", + "tempfile", + "textwrap", + "toml", + "uniffi_internal_macros", + "uniffi_meta", + "uniffi_pipeline", + "uniffi_udl", +] + +[[package]] +name = "uniffi_build" +version = "0.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e55c05228f4858bb258f651d21d743fcc1fe5a2ec20d3c0f9daefddb105ee4d" +dependencies = [ + "anyhow", + "camino", + "uniffi_bindgen", +] + +[[package]] +name = "uniffi_core" +version = "0.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e7a5a038ebffe8f4cf91416b154ef3c2468b18e828b7009e01b1b99938089f9" +dependencies = [ + "anyhow", + "bytes", + "once_cell", + "static_assertions", +] + +[[package]] +name = "uniffi_internal_macros" +version = "0.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3c2a6f93e7b73726e2015696ece25ca0ac5a5f1cf8d6a7ab5214dd0a01d2edf" +dependencies = [ + "anyhow", + "indexmap 2.11.4", + "proc-macro2", + "quote", + "syn 2.0.106", +] + +[[package]] +name = "uniffi_macros" +version = "0.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64c6309fc36c7992afc03bc0c5b059c656bccbef3f2a4bc362980017f8936141" +dependencies = [ + "camino", + "fs-err", + "once_cell", + "proc-macro2", + "quote", + "serde", + "syn 2.0.106", + "toml", + "uniffi_meta", +] + +[[package]] +name = "uniffi_meta" +version = "0.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a138823392dba19b0aa494872689f97d0ee157de5852e2bec157ce6de9cdc22" +dependencies = [ + "anyhow", + "siphasher", + "uniffi_internal_macros", + "uniffi_pipeline", +] + +[[package]] +name = "uniffi_pipeline" +version = "0.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c27c4b515d25f8e53cc918e238c39a79c3144a40eaf2e51c4a7958973422c29" +dependencies = [ + "anyhow", + "heck 0.5.0", + "indexmap 2.11.4", + "tempfile", + "uniffi_internal_macros", +] + +[[package]] +name = "uniffi_udl" +version = "0.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0adacdd848aeed7af4f5af7d2f621d5e82531325d405e29463482becfdeafca" +dependencies = [ + "anyhow", + "textwrap", + "uniffi_meta", + "weedle2", +] + [[package]] name = "untrusted" version = "0.9.0" @@ -6117,6 +6448,15 @@ dependencies = [ "zip", ] +[[package]] +name = "weedle2" +version = "5.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "998d2c24ec099a87daf9467808859f9d82b61f1d9c9701251aea037f514eae0e" +dependencies = [ + "nom", +] + [[package]] name = "weezl" version = "0.1.10" diff --git a/Cargo.toml b/Cargo.toml index c1808ff0a..a0ddc235d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,6 +5,7 @@ members = [ "livekit-api", "livekit-protocol", "livekit-ffi", + "livekit-uniffi", "livekit-runtime", "libwebrtc", "soxr-sys", @@ -25,7 +26,7 @@ members = [ "examples/save_to_disk", "examples/send_bytes", "examples/webhooks", - "examples/wgpu_room", + "examples/wgpu_room" ] [workspace.dependencies] diff --git a/livekit-uniffi/Cargo.toml b/livekit-uniffi/Cargo.toml new file mode 100644 index 000000000..3c37e55b2 --- /dev/null +++ b/livekit-uniffi/Cargo.toml @@ -0,0 +1,26 @@ +[package] +name = "livekit-uniffi" +version = "0.1.0" +edition = "2021" +license = "Apache-2.0" +description = "Experimental FFI interface using UniFFI" +repository = "https://github.com/livekit/rust-sdks" +readme = "README.md" + +[dependencies] +livekit-protocol = { workspace = true } +livekit-api = { workspace = true } +uniffi = { version = "0.30.0", features = ["cli", "scaffolding-ffi-buffer-fns"] } +log = "0.4.28" +tokio = { version = "1.48.0", features = ["sync"] } +once_cell = "1.21.3" + +[build-dependencies] +uniffi = { version = "0.30.0", features = ["build", "scaffolding-ffi-buffer-fns"] } + +[lib] +crate-type = ["cdylib", "staticlib"] + +[[bin]] +name = "uniffi-bindgen" +path = "bindgen.rs" diff --git a/livekit-uniffi/Package.swift b/livekit-uniffi/Package.swift new file mode 100644 index 000000000..5af5626ff --- /dev/null +++ b/livekit-uniffi/Package.swift @@ -0,0 +1,36 @@ +// swift-tools-version:6.0 +// (Xcode16.0+) + +// For local testing, run ./swift.sh to generate the xcframework + +import PackageDescription + +let package = Package( + name: "LiveKitFFI", + platforms: [ + .iOS(.v13), + .macOS(.v10_15), + .macCatalyst(.v14), + .visionOS(.v2), + .tvOS(.v17), + ], + products: [ + .library( + name: "LiveKitFFI", + targets: ["LiveKitFFI"] + ) + ], + targets: [ + .binaryTarget( + name: "LiveKitFFIBinary", + path: "../target/LiveKitFFI.xcframework" + ), + .target( + name: "LiveKitFFI", + dependencies: ["LiveKitFFIBinary"], + path: "generated/swift", + sources: ["livekit_uniffi.swift"], + publicHeadersPath: "." + ) + ] +) diff --git a/livekit-uniffi/README.md b/livekit-uniffi/README.md new file mode 100644 index 000000000..68df9a38c --- /dev/null +++ b/livekit-uniffi/README.md @@ -0,0 +1,19 @@ +# LiveKit UniFFI + +Experimental FFI interface using [UniFFI](https://mozilla.github.io/uniffi-rs/latest/). + +At this stage in development, this interface will not attempt to replace the existing FFI interface defined in [_livekit-ffi_](../livekit-ffi/). Instead, it will focus on exposing core business logic that can be cleanly modularized and adopted by client SDKs incrementally. + +## Functionality exposed + +- [x] Access token generation and verification + +## Generating bindings + +Use the _bindgen.sh_ script to generate language bindings for Swift, Kotlin, and Python. + +Later, this script will integrate community binding generators to support more languages. + +## Python test + +See the _python_test_ for a simple example of consuming the generated bindings. You will need to manually copy the compiled _livlivekit_uniffi_ to the same directory as the generated Python bindings before running—this will be automated shortly. diff --git a/livekit-uniffi/bindgen.rs b/livekit-uniffi/bindgen.rs new file mode 100644 index 000000000..7eb9d1172 --- /dev/null +++ b/livekit-uniffi/bindgen.rs @@ -0,0 +1,19 @@ +// Copyright 2025 LiveKit, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/// This binary is included to allow invoking the UniFFI bindgen CLI from Cargo: +/// `cargo run --bin uniffi-bindgen generate ...` +fn main() { + uniffi::uniffi_bindgen_main() +} diff --git a/livekit-uniffi/bindgen.sh b/livekit-uniffi/bindgen.sh new file mode 100755 index 000000000..ab8b4cb7b --- /dev/null +++ b/livekit-uniffi/bindgen.sh @@ -0,0 +1,17 @@ +#!/bin/bash +set -e + +cargo build --release + +bindgen() { + local lang=$1 + # TODO: set the library extension based on platform (i.e., .so, .dylib, .dll) + cargo run --bin uniffi-bindgen generate \ + --library ../target/release/liblivekit_uniffi.dylib \ + --language "$lang" \ + --out-dir "generated/$lang" +} + +bindgen swift +bindgen kotlin +bindgen python diff --git a/livekit-uniffi/generated/kotlin/uniffi/livekit_uniffi/livekit_uniffi.kt b/livekit-uniffi/generated/kotlin/uniffi/livekit_uniffi/livekit_uniffi.kt new file mode 100644 index 000000000..f26577da0 --- /dev/null +++ b/livekit-uniffi/generated/kotlin/uniffi/livekit_uniffi/livekit_uniffi.kt @@ -0,0 +1,2059 @@ +// 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.livekit_uniffi + +// 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 +import kotlin.coroutines.resume +import kotlinx.coroutines.CancellableContinuation +import kotlinx.coroutines.DelicateCoroutinesApi +import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.Job +import kotlinx.coroutines.launch +import kotlinx.coroutines.suspendCancellableCoroutine + +// This is a helper for safely working with byte buffers returned from the Rust code. +// A rust-owned buffer is represented by its capacity, its current length, and a +// pointer to the underlying data. + +/** + * @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.ffi_livekit_uniffi_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.ffi_livekit_uniffi_rustbuffer_free(buf, status) + } + } + + @Suppress("TooGenericExceptionThrown") + fun asByteBuffer() = + this.data?.getByteBuffer(0, this.len.toLong())?.also { + it.order(ByteOrder.BIG_ENDIAN) + } +} + +// 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()) + } + } +} +// Initial value and increment amount for handles. +// These ensure that Kotlin-generated handles always have the lowest bit set +private const val UNIFFI_HANDLEMAP_INITIAL = 1.toLong() +private const val UNIFFI_HANDLEMAP_DELTA = 2.toLong() + +// 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() + // Start + private val counter = java.util.concurrent.atomic.AtomicLong(UNIFFI_HANDLEMAP_INITIAL) + + 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(UNIFFI_HANDLEMAP_DELTA) + map.put(handle, obj) + return handle + } + + // Clone a handle, creating a new one + fun clone(handle: Long): Long { + val obj = map.get(handle) ?: throw InternalException("UniffiHandleMap.clone: Invalid handle") + return insert(obj) + } + + // 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 "livekit_uniffi" +} + +// Define FFI callback types +internal interface UniffiRustFutureContinuationCallback : com.sun.jna.Callback { + fun callback(`data`: Long,`pollResult`: Byte,) +} +internal interface UniffiForeignFutureDroppedCallback : com.sun.jna.Callback { + fun callback(`handle`: Long,) +} +internal interface UniffiCallbackInterfaceFree : com.sun.jna.Callback { + fun callback(`handle`: Long,) +} +internal interface UniffiCallbackInterfaceClone : com.sun.jna.Callback { + fun callback(`handle`: Long,) + : Long +} +@Structure.FieldOrder("handle", "free") +internal open class UniffiForeignFutureDroppedCallbackStruct( + @JvmField internal var `handle`: Long = 0.toLong(), + @JvmField internal var `free`: UniffiForeignFutureDroppedCallback? = null, +) : Structure() { + class UniffiByValue( + `handle`: Long = 0.toLong(), + `free`: UniffiForeignFutureDroppedCallback? = null, + ): UniffiForeignFutureDroppedCallbackStruct(`handle`,`free`,), Structure.ByValue + + internal fun uniffiSetValue(other: UniffiForeignFutureDroppedCallbackStruct) { + `handle` = other.`handle` + `free` = other.`free` + } + +} +@Structure.FieldOrder("returnValue", "callStatus") +internal open class UniffiForeignFutureResultU8( + @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(), + ): UniffiForeignFutureResultU8(`returnValue`,`callStatus`,), Structure.ByValue + + internal fun uniffiSetValue(other: UniffiForeignFutureResultU8) { + `returnValue` = other.`returnValue` + `callStatus` = other.`callStatus` + } + +} +internal interface UniffiForeignFutureCompleteU8 : com.sun.jna.Callback { + fun callback(`callbackData`: Long,`result`: UniffiForeignFutureResultU8.UniffiByValue,) +} +@Structure.FieldOrder("returnValue", "callStatus") +internal open class UniffiForeignFutureResultI8( + @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(), + ): UniffiForeignFutureResultI8(`returnValue`,`callStatus`,), Structure.ByValue + + internal fun uniffiSetValue(other: UniffiForeignFutureResultI8) { + `returnValue` = other.`returnValue` + `callStatus` = other.`callStatus` + } + +} +internal interface UniffiForeignFutureCompleteI8 : com.sun.jna.Callback { + fun callback(`callbackData`: Long,`result`: UniffiForeignFutureResultI8.UniffiByValue,) +} +@Structure.FieldOrder("returnValue", "callStatus") +internal open class UniffiForeignFutureResultU16( + @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(), + ): UniffiForeignFutureResultU16(`returnValue`,`callStatus`,), Structure.ByValue + + internal fun uniffiSetValue(other: UniffiForeignFutureResultU16) { + `returnValue` = other.`returnValue` + `callStatus` = other.`callStatus` + } + +} +internal interface UniffiForeignFutureCompleteU16 : com.sun.jna.Callback { + fun callback(`callbackData`: Long,`result`: UniffiForeignFutureResultU16.UniffiByValue,) +} +@Structure.FieldOrder("returnValue", "callStatus") +internal open class UniffiForeignFutureResultI16( + @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(), + ): UniffiForeignFutureResultI16(`returnValue`,`callStatus`,), Structure.ByValue + + internal fun uniffiSetValue(other: UniffiForeignFutureResultI16) { + `returnValue` = other.`returnValue` + `callStatus` = other.`callStatus` + } + +} +internal interface UniffiForeignFutureCompleteI16 : com.sun.jna.Callback { + fun callback(`callbackData`: Long,`result`: UniffiForeignFutureResultI16.UniffiByValue,) +} +@Structure.FieldOrder("returnValue", "callStatus") +internal open class UniffiForeignFutureResultU32( + @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(), + ): UniffiForeignFutureResultU32(`returnValue`,`callStatus`,), Structure.ByValue + + internal fun uniffiSetValue(other: UniffiForeignFutureResultU32) { + `returnValue` = other.`returnValue` + `callStatus` = other.`callStatus` + } + +} +internal interface UniffiForeignFutureCompleteU32 : com.sun.jna.Callback { + fun callback(`callbackData`: Long,`result`: UniffiForeignFutureResultU32.UniffiByValue,) +} +@Structure.FieldOrder("returnValue", "callStatus") +internal open class UniffiForeignFutureResultI32( + @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(), + ): UniffiForeignFutureResultI32(`returnValue`,`callStatus`,), Structure.ByValue + + internal fun uniffiSetValue(other: UniffiForeignFutureResultI32) { + `returnValue` = other.`returnValue` + `callStatus` = other.`callStatus` + } + +} +internal interface UniffiForeignFutureCompleteI32 : com.sun.jna.Callback { + fun callback(`callbackData`: Long,`result`: UniffiForeignFutureResultI32.UniffiByValue,) +} +@Structure.FieldOrder("returnValue", "callStatus") +internal open class UniffiForeignFutureResultU64( + @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(), + ): UniffiForeignFutureResultU64(`returnValue`,`callStatus`,), Structure.ByValue + + internal fun uniffiSetValue(other: UniffiForeignFutureResultU64) { + `returnValue` = other.`returnValue` + `callStatus` = other.`callStatus` + } + +} +internal interface UniffiForeignFutureCompleteU64 : com.sun.jna.Callback { + fun callback(`callbackData`: Long,`result`: UniffiForeignFutureResultU64.UniffiByValue,) +} +@Structure.FieldOrder("returnValue", "callStatus") +internal open class UniffiForeignFutureResultI64( + @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(), + ): UniffiForeignFutureResultI64(`returnValue`,`callStatus`,), Structure.ByValue + + internal fun uniffiSetValue(other: UniffiForeignFutureResultI64) { + `returnValue` = other.`returnValue` + `callStatus` = other.`callStatus` + } + +} +internal interface UniffiForeignFutureCompleteI64 : com.sun.jna.Callback { + fun callback(`callbackData`: Long,`result`: UniffiForeignFutureResultI64.UniffiByValue,) +} +@Structure.FieldOrder("returnValue", "callStatus") +internal open class UniffiForeignFutureResultF32( + @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(), + ): UniffiForeignFutureResultF32(`returnValue`,`callStatus`,), Structure.ByValue + + internal fun uniffiSetValue(other: UniffiForeignFutureResultF32) { + `returnValue` = other.`returnValue` + `callStatus` = other.`callStatus` + } + +} +internal interface UniffiForeignFutureCompleteF32 : com.sun.jna.Callback { + fun callback(`callbackData`: Long,`result`: UniffiForeignFutureResultF32.UniffiByValue,) +} +@Structure.FieldOrder("returnValue", "callStatus") +internal open class UniffiForeignFutureResultF64( + @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(), + ): UniffiForeignFutureResultF64(`returnValue`,`callStatus`,), Structure.ByValue + + internal fun uniffiSetValue(other: UniffiForeignFutureResultF64) { + `returnValue` = other.`returnValue` + `callStatus` = other.`callStatus` + } + +} +internal interface UniffiForeignFutureCompleteF64 : com.sun.jna.Callback { + fun callback(`callbackData`: Long,`result`: UniffiForeignFutureResultF64.UniffiByValue,) +} +@Structure.FieldOrder("returnValue", "callStatus") +internal open class UniffiForeignFutureResultRustBuffer( + @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(), + ): UniffiForeignFutureResultRustBuffer(`returnValue`,`callStatus`,), Structure.ByValue + + internal fun uniffiSetValue(other: UniffiForeignFutureResultRustBuffer) { + `returnValue` = other.`returnValue` + `callStatus` = other.`callStatus` + } + +} +internal interface UniffiForeignFutureCompleteRustBuffer : com.sun.jna.Callback { + fun callback(`callbackData`: Long,`result`: UniffiForeignFutureResultRustBuffer.UniffiByValue,) +} +@Structure.FieldOrder("callStatus") +internal open class UniffiForeignFutureResultVoid( + @JvmField internal var `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(), +) : Structure() { + class UniffiByValue( + `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(), + ): UniffiForeignFutureResultVoid(`callStatus`,), Structure.ByValue + + internal fun uniffiSetValue(other: UniffiForeignFutureResultVoid) { + `callStatus` = other.`callStatus` + } + +} +internal interface UniffiForeignFutureCompleteVoid : com.sun.jna.Callback { + fun callback(`callbackData`: Long,`result`: UniffiForeignFutureResultVoid.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. + +// For large crates we prevent `MethodTooLargeException` (see #2340) +// N.B. the name of the extension is very misleading, since it is +// rather `InterfaceTooLargeException`, caused by too many methods +// in the interface for large crates. +// +// By splitting the otherwise huge interface into two parts +// * UniffiLib (this) +// * IntegrityCheckingUniffiLib +// And all checksum methods are put into `IntegrityCheckingUniffiLib` +// we allow for ~2x as many methods in the UniffiLib interface. +// +// Note: above all written when we used JNA's `loadIndirect` etc. +// We now use JNA's "direct mapping" - unclear if same considerations apply exactly. +internal object IntegrityCheckingUniffiLib { + init { + Native.register(IntegrityCheckingUniffiLib::class.java, findLibraryName(componentName = "livekit_uniffi")) + uniffiCheckContractApiVersion(this) + uniffiCheckApiChecksums(this) + } + external fun uniffi_livekit_uniffi_checksum_func_build_version( + ): Short + external fun uniffi_livekit_uniffi_checksum_func_generate_token( + ): Short + external fun uniffi_livekit_uniffi_checksum_func_log_forward_bootstrap( + ): Short + external fun uniffi_livekit_uniffi_checksum_func_log_forward_receive( + ): Short + external fun uniffi_livekit_uniffi_checksum_func_verify_token( + ): Short + external fun ffi_livekit_uniffi_uniffi_contract_version( + ): Int + + +} + +internal object UniffiLib { + + + init { + Native.register(UniffiLib::class.java, findLibraryName(componentName = "livekit_uniffi")) + + } + external fun uniffi_livekit_uniffi_fn_func_build_version(uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + external fun uniffi_livekit_uniffi_fn_func_generate_token(`options`: RustBuffer.ByValue,`credentials`: RustBuffer.ByValue,uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + external fun uniffi_livekit_uniffi_fn_func_log_forward_bootstrap(`level`: RustBuffer.ByValue,uniffi_out_err: UniffiRustCallStatus, + ): Unit + external fun uniffi_livekit_uniffi_fn_func_log_forward_receive( + ): Long + external fun uniffi_livekit_uniffi_fn_func_verify_token(`token`: RustBuffer.ByValue,`credentials`: RustBuffer.ByValue,uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + external fun ffi_livekit_uniffi_rustbuffer_alloc(`size`: Long,uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + external fun ffi_livekit_uniffi_rustbuffer_from_bytes(`bytes`: ForeignBytes.ByValue,uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + external fun ffi_livekit_uniffi_rustbuffer_free(`buf`: RustBuffer.ByValue,uniffi_out_err: UniffiRustCallStatus, + ): Unit + external fun ffi_livekit_uniffi_rustbuffer_reserve(`buf`: RustBuffer.ByValue,`additional`: Long,uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + external fun ffi_livekit_uniffi_rust_future_poll_u8(`handle`: Long,`callback`: UniffiRustFutureContinuationCallback,`callbackData`: Long, + ): Unit + external fun ffi_livekit_uniffi_rust_future_cancel_u8(`handle`: Long, + ): Unit + external fun ffi_livekit_uniffi_rust_future_free_u8(`handle`: Long, + ): Unit + external fun ffi_livekit_uniffi_rust_future_complete_u8(`handle`: Long,uniffi_out_err: UniffiRustCallStatus, + ): Byte + external fun ffi_livekit_uniffi_rust_future_poll_i8(`handle`: Long,`callback`: UniffiRustFutureContinuationCallback,`callbackData`: Long, + ): Unit + external fun ffi_livekit_uniffi_rust_future_cancel_i8(`handle`: Long, + ): Unit + external fun ffi_livekit_uniffi_rust_future_free_i8(`handle`: Long, + ): Unit + external fun ffi_livekit_uniffi_rust_future_complete_i8(`handle`: Long,uniffi_out_err: UniffiRustCallStatus, + ): Byte + external fun ffi_livekit_uniffi_rust_future_poll_u16(`handle`: Long,`callback`: UniffiRustFutureContinuationCallback,`callbackData`: Long, + ): Unit + external fun ffi_livekit_uniffi_rust_future_cancel_u16(`handle`: Long, + ): Unit + external fun ffi_livekit_uniffi_rust_future_free_u16(`handle`: Long, + ): Unit + external fun ffi_livekit_uniffi_rust_future_complete_u16(`handle`: Long,uniffi_out_err: UniffiRustCallStatus, + ): Short + external fun ffi_livekit_uniffi_rust_future_poll_i16(`handle`: Long,`callback`: UniffiRustFutureContinuationCallback,`callbackData`: Long, + ): Unit + external fun ffi_livekit_uniffi_rust_future_cancel_i16(`handle`: Long, + ): Unit + external fun ffi_livekit_uniffi_rust_future_free_i16(`handle`: Long, + ): Unit + external fun ffi_livekit_uniffi_rust_future_complete_i16(`handle`: Long,uniffi_out_err: UniffiRustCallStatus, + ): Short + external fun ffi_livekit_uniffi_rust_future_poll_u32(`handle`: Long,`callback`: UniffiRustFutureContinuationCallback,`callbackData`: Long, + ): Unit + external fun ffi_livekit_uniffi_rust_future_cancel_u32(`handle`: Long, + ): Unit + external fun ffi_livekit_uniffi_rust_future_free_u32(`handle`: Long, + ): Unit + external fun ffi_livekit_uniffi_rust_future_complete_u32(`handle`: Long,uniffi_out_err: UniffiRustCallStatus, + ): Int + external fun ffi_livekit_uniffi_rust_future_poll_i32(`handle`: Long,`callback`: UniffiRustFutureContinuationCallback,`callbackData`: Long, + ): Unit + external fun ffi_livekit_uniffi_rust_future_cancel_i32(`handle`: Long, + ): Unit + external fun ffi_livekit_uniffi_rust_future_free_i32(`handle`: Long, + ): Unit + external fun ffi_livekit_uniffi_rust_future_complete_i32(`handle`: Long,uniffi_out_err: UniffiRustCallStatus, + ): Int + external fun ffi_livekit_uniffi_rust_future_poll_u64(`handle`: Long,`callback`: UniffiRustFutureContinuationCallback,`callbackData`: Long, + ): Unit + external fun ffi_livekit_uniffi_rust_future_cancel_u64(`handle`: Long, + ): Unit + external fun ffi_livekit_uniffi_rust_future_free_u64(`handle`: Long, + ): Unit + external fun ffi_livekit_uniffi_rust_future_complete_u64(`handle`: Long,uniffi_out_err: UniffiRustCallStatus, + ): Long + external fun ffi_livekit_uniffi_rust_future_poll_i64(`handle`: Long,`callback`: UniffiRustFutureContinuationCallback,`callbackData`: Long, + ): Unit + external fun ffi_livekit_uniffi_rust_future_cancel_i64(`handle`: Long, + ): Unit + external fun ffi_livekit_uniffi_rust_future_free_i64(`handle`: Long, + ): Unit + external fun ffi_livekit_uniffi_rust_future_complete_i64(`handle`: Long,uniffi_out_err: UniffiRustCallStatus, + ): Long + external fun ffi_livekit_uniffi_rust_future_poll_f32(`handle`: Long,`callback`: UniffiRustFutureContinuationCallback,`callbackData`: Long, + ): Unit + external fun ffi_livekit_uniffi_rust_future_cancel_f32(`handle`: Long, + ): Unit + external fun ffi_livekit_uniffi_rust_future_free_f32(`handle`: Long, + ): Unit + external fun ffi_livekit_uniffi_rust_future_complete_f32(`handle`: Long,uniffi_out_err: UniffiRustCallStatus, + ): Float + external fun ffi_livekit_uniffi_rust_future_poll_f64(`handle`: Long,`callback`: UniffiRustFutureContinuationCallback,`callbackData`: Long, + ): Unit + external fun ffi_livekit_uniffi_rust_future_cancel_f64(`handle`: Long, + ): Unit + external fun ffi_livekit_uniffi_rust_future_free_f64(`handle`: Long, + ): Unit + external fun ffi_livekit_uniffi_rust_future_complete_f64(`handle`: Long,uniffi_out_err: UniffiRustCallStatus, + ): Double + external fun ffi_livekit_uniffi_rust_future_poll_rust_buffer(`handle`: Long,`callback`: UniffiRustFutureContinuationCallback,`callbackData`: Long, + ): Unit + external fun ffi_livekit_uniffi_rust_future_cancel_rust_buffer(`handle`: Long, + ): Unit + external fun ffi_livekit_uniffi_rust_future_free_rust_buffer(`handle`: Long, + ): Unit + external fun ffi_livekit_uniffi_rust_future_complete_rust_buffer(`handle`: Long,uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + external fun ffi_livekit_uniffi_rust_future_poll_void(`handle`: Long,`callback`: UniffiRustFutureContinuationCallback,`callbackData`: Long, + ): Unit + external fun ffi_livekit_uniffi_rust_future_cancel_void(`handle`: Long, + ): Unit + external fun ffi_livekit_uniffi_rust_future_free_void(`handle`: Long, + ): Unit + external fun ffi_livekit_uniffi_rust_future_complete_void(`handle`: Long,uniffi_out_err: UniffiRustCallStatus, + ): Unit + + +} + +private fun uniffiCheckContractApiVersion(lib: IntegrityCheckingUniffiLib) { + // Get the bindings contract version from our ComponentInterface + val bindings_contract_version = 30 + // Get the scaffolding contract version by calling the into the dylib + val scaffolding_contract_version = lib.ffi_livekit_uniffi_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: IntegrityCheckingUniffiLib) { + if (lib.uniffi_livekit_uniffi_checksum_func_build_version() != 45072.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_livekit_uniffi_checksum_func_generate_token() != 29823.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_livekit_uniffi_checksum_func_log_forward_bootstrap() != 28675.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_livekit_uniffi_checksum_func_log_forward_receive() != 7863.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_livekit_uniffi_checksum_func_verify_token() != 47517.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } +} + +/** + * @suppress + */ +public fun uniffiEnsureInitialized() { + IntegrityCheckingUniffiLib + // UniffiLib() initialized as objects are used, but we still need to explicitly + // reference it so initialization across crates works as expected. + UniffiLib +} + +// Async support +// Async return type handlers + +internal const val UNIFFI_RUST_FUTURE_POLL_READY = 0.toByte() +internal const val UNIFFI_RUST_FUTURE_POLL_WAKE = 1.toByte() + +internal val uniffiContinuationHandleMap = UniffiHandleMap>() + +// FFI type for Rust future continuations +internal object uniffiRustFutureContinuationCallbackImpl: UniffiRustFutureContinuationCallback { + override fun callback(data: Long, pollResult: Byte) { + uniffiContinuationHandleMap.remove(data).resume(pollResult) + } +} + +internal suspend fun uniffiRustCallAsync( + rustFuture: Long, + pollFunc: (Long, UniffiRustFutureContinuationCallback, Long) -> Unit, + completeFunc: (Long, UniffiRustCallStatus) -> F, + freeFunc: (Long) -> Unit, + liftFunc: (F) -> T, + errorHandler: UniffiRustCallStatusErrorHandler +): T { + try { + do { + val pollResult = suspendCancellableCoroutine { continuation -> + pollFunc( + rustFuture, + uniffiRustFutureContinuationCallbackImpl, + uniffiContinuationHandleMap.insert(continuation) + ) + } + } while (pollResult != UNIFFI_RUST_FUTURE_POLL_READY); + + return liftFunc( + uniffiRustCallWithError(errorHandler, { status -> completeFunc(rustFuture, status) }) + ) + } finally { + freeFunc(rustFuture) + } +} + +// 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?) { + for (arg in args) { + when (arg) { + is Disposable -> arg.destroy() + is ArrayList<*> -> { + for (idx in arg.indices) { + val element = arg[idx] + if (element is Disposable) { + element.destroy() + } + } + } + is Map<*, *> -> { + for (element in arg.values) { + if (element is Disposable) { + element.destroy() + } + } + } + is Iterable<*> -> { + for (element in arg) { + if (element is Disposable) { + element.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 + } + } + +/** + * Placeholder object used to signal that we're constructing an interface with a FFI handle. + * + * This is the first argument for interface constructors that input a raw handle. It exists is that + * so we can avoid signature conflicts when an interface has a regular constructor than inputs a + * Long. + * + * @suppress + * */ +object UniffiWithHandle + +/** + * Used to instantiate an interface without an actual pointer, for fakes in tests, mostly. + * + * @suppress + * */ +object NoHandle + +/** + * @suppress + */ +public object FfiConverterUInt: FfiConverter { + override fun lift(value: Int): UInt { + return value.toUInt() + } + + override fun read(buf: ByteBuffer): UInt { + return lift(buf.getInt()) + } + + override fun lower(value: UInt): Int { + return value.toInt() + } + + override fun allocationSize(value: UInt) = 4UL + + override fun write(value: UInt, buf: ByteBuffer) { + buf.putInt(value.toInt()) + } +} + +/** + * @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) + } +} + + +/** + * @suppress + */ +public object FfiConverterDuration: FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): java.time.Duration { + // Type mismatch (should be u64) but we check for overflow/underflow below + val seconds = buf.getLong() + // Type mismatch (should be u32) but we check for overflow/underflow below + val nanoseconds = buf.getInt().toLong() + if (seconds < 0) { + throw java.time.DateTimeException("Duration exceeds minimum or maximum value supported by uniffi") + } + if (nanoseconds < 0) { + throw java.time.DateTimeException("Duration nanoseconds exceed minimum or maximum supported by uniffi") + } + return java.time.Duration.ofSeconds(seconds, nanoseconds) + } + + // 8 bytes for seconds, 4 bytes for nanoseconds + override fun allocationSize(value: java.time.Duration) = 12UL + + override fun write(value: java.time.Duration, buf: ByteBuffer) { + if (value.seconds < 0) { + // Rust does not support negative Durations + throw IllegalArgumentException("Invalid duration, must be non-negative") + } + + if (value.nano < 0) { + // Java docs provide guarantee that nano will always be positive, so this should be impossible + // See: https://docs.oracle.com/javase/8/docs/api/java/time/Duration.html + throw IllegalArgumentException("Invalid duration, nano value must be non-negative") + } + + // Type mismatch (should be u64) but since Rust doesn't support negative durations we should be OK + buf.putLong(value.seconds) + // Type mismatch (should be u32) but since values will always be between 0 and 999,999,999 it should be OK + buf.putInt(value.nano) + } +} + + + +/** + * API credentials for access token generation and verification. + */ +data class ApiCredentials ( + var `key`: kotlin.String + , + var `secret`: kotlin.String + +){ + + + + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypeApiCredentials: FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): ApiCredentials { + return ApiCredentials( + FfiConverterString.read(buf), + FfiConverterString.read(buf), + ) + } + + override fun allocationSize(value: ApiCredentials) = ( + FfiConverterString.allocationSize(value.`key`) + + FfiConverterString.allocationSize(value.`secret`) + ) + + override fun write(value: ApiCredentials, buf: ByteBuffer) { + FfiConverterString.write(value.`key`, buf) + FfiConverterString.write(value.`secret`, buf) + } +} + + + +/** + * Claims decoded from a valid access token. + */ +data class Claims ( + var `exp`: kotlin.ULong + , + var `iss`: kotlin.String + , + var `nbf`: kotlin.ULong + , + var `sub`: kotlin.String + , + var `name`: kotlin.String + , + var `video`: VideoGrants + , + var `sip`: SipGrants + , + var `sha256`: kotlin.String + , + var `metadata`: kotlin.String + , + var `attributes`: Map + , + var `roomName`: kotlin.String + +){ + + + + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypeClaims: FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): Claims { + return Claims( + FfiConverterULong.read(buf), + FfiConverterString.read(buf), + FfiConverterULong.read(buf), + FfiConverterString.read(buf), + FfiConverterString.read(buf), + FfiConverterTypeVideoGrants.read(buf), + FfiConverterTypeSIPGrants.read(buf), + FfiConverterString.read(buf), + FfiConverterString.read(buf), + FfiConverterMapStringString.read(buf), + FfiConverterString.read(buf), + ) + } + + override fun allocationSize(value: Claims) = ( + FfiConverterULong.allocationSize(value.`exp`) + + FfiConverterString.allocationSize(value.`iss`) + + FfiConverterULong.allocationSize(value.`nbf`) + + FfiConverterString.allocationSize(value.`sub`) + + FfiConverterString.allocationSize(value.`name`) + + FfiConverterTypeVideoGrants.allocationSize(value.`video`) + + FfiConverterTypeSIPGrants.allocationSize(value.`sip`) + + FfiConverterString.allocationSize(value.`sha256`) + + FfiConverterString.allocationSize(value.`metadata`) + + FfiConverterMapStringString.allocationSize(value.`attributes`) + + FfiConverterString.allocationSize(value.`roomName`) + ) + + override fun write(value: Claims, buf: ByteBuffer) { + FfiConverterULong.write(value.`exp`, buf) + FfiConverterString.write(value.`iss`, buf) + FfiConverterULong.write(value.`nbf`, buf) + FfiConverterString.write(value.`sub`, buf) + FfiConverterString.write(value.`name`, buf) + FfiConverterTypeVideoGrants.write(value.`video`, buf) + FfiConverterTypeSIPGrants.write(value.`sip`, buf) + FfiConverterString.write(value.`sha256`, buf) + FfiConverterString.write(value.`metadata`, buf) + FfiConverterMapStringString.write(value.`attributes`, buf) + FfiConverterString.write(value.`roomName`, buf) + } +} + + + +data class LogForwardEntry ( + var `level`: LogForwardLevel + , + var `target`: kotlin.String + , + var `file`: kotlin.String? + , + var `line`: kotlin.UInt? + , + var `message`: kotlin.String + +){ + + + + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypeLogForwardEntry: FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): LogForwardEntry { + return LogForwardEntry( + FfiConverterTypeLogForwardLevel.read(buf), + FfiConverterString.read(buf), + FfiConverterOptionalString.read(buf), + FfiConverterOptionalUInt.read(buf), + FfiConverterString.read(buf), + ) + } + + override fun allocationSize(value: LogForwardEntry) = ( + FfiConverterTypeLogForwardLevel.allocationSize(value.`level`) + + FfiConverterString.allocationSize(value.`target`) + + FfiConverterOptionalString.allocationSize(value.`file`) + + FfiConverterOptionalUInt.allocationSize(value.`line`) + + FfiConverterString.allocationSize(value.`message`) + ) + + override fun write(value: LogForwardEntry, buf: ByteBuffer) { + FfiConverterTypeLogForwardLevel.write(value.`level`, buf) + FfiConverterString.write(value.`target`, buf) + FfiConverterOptionalString.write(value.`file`, buf) + FfiConverterOptionalUInt.write(value.`line`, buf) + FfiConverterString.write(value.`message`, buf) + } +} + + + +/** + * SIP grants + * + * Maps to the JWT's `sip` field. + + */ +data class SipGrants ( + var `admin`: kotlin.Boolean + , + var `call`: kotlin.Boolean + +){ + + + + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypeSIPGrants: FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): SipGrants { + return SipGrants( + FfiConverterBoolean.read(buf), + FfiConverterBoolean.read(buf), + ) + } + + override fun allocationSize(value: SipGrants) = ( + FfiConverterBoolean.allocationSize(value.`admin`) + + FfiConverterBoolean.allocationSize(value.`call`) + ) + + override fun write(value: SipGrants, buf: ByteBuffer) { + FfiConverterBoolean.write(value.`admin`, buf) + FfiConverterBoolean.write(value.`call`, buf) + } +} + + + +/** + * Options used for generating an access token. + * + * Any fields left empty will use the token generator's defaults. + + */ +data class TokenOptions ( + var `ttl`: java.time.Duration? = null + , + var `videoGrants`: VideoGrants? = null + , + var `sipGrants`: SipGrants? = null + , + var `identity`: kotlin.String? = null + , + var `name`: kotlin.String? = null + , + var `metadata`: kotlin.String? = null + , + var `attributes`: Map? = null + , + var `sha256`: kotlin.String? = null + , + var `roomName`: kotlin.String? = null + +){ + + + + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypeTokenOptions: FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): TokenOptions { + return TokenOptions( + FfiConverterOptionalDuration.read(buf), + FfiConverterOptionalTypeVideoGrants.read(buf), + FfiConverterOptionalTypeSIPGrants.read(buf), + FfiConverterOptionalString.read(buf), + FfiConverterOptionalString.read(buf), + FfiConverterOptionalString.read(buf), + FfiConverterOptionalMapStringString.read(buf), + FfiConverterOptionalString.read(buf), + FfiConverterOptionalString.read(buf), + ) + } + + override fun allocationSize(value: TokenOptions) = ( + FfiConverterOptionalDuration.allocationSize(value.`ttl`) + + FfiConverterOptionalTypeVideoGrants.allocationSize(value.`videoGrants`) + + FfiConverterOptionalTypeSIPGrants.allocationSize(value.`sipGrants`) + + FfiConverterOptionalString.allocationSize(value.`identity`) + + FfiConverterOptionalString.allocationSize(value.`name`) + + FfiConverterOptionalString.allocationSize(value.`metadata`) + + FfiConverterOptionalMapStringString.allocationSize(value.`attributes`) + + FfiConverterOptionalString.allocationSize(value.`sha256`) + + FfiConverterOptionalString.allocationSize(value.`roomName`) + ) + + override fun write(value: TokenOptions, buf: ByteBuffer) { + FfiConverterOptionalDuration.write(value.`ttl`, buf) + FfiConverterOptionalTypeVideoGrants.write(value.`videoGrants`, buf) + FfiConverterOptionalTypeSIPGrants.write(value.`sipGrants`, buf) + FfiConverterOptionalString.write(value.`identity`, buf) + FfiConverterOptionalString.write(value.`name`, buf) + FfiConverterOptionalString.write(value.`metadata`, buf) + FfiConverterOptionalMapStringString.write(value.`attributes`, buf) + FfiConverterOptionalString.write(value.`sha256`, buf) + FfiConverterOptionalString.write(value.`roomName`, buf) + } +} + + + +/** + * Room permissions + * + * Maps to the JWT's `video` field. + */ +data class VideoGrants ( + var `roomCreate`: kotlin.Boolean + , + var `roomList`: kotlin.Boolean + , + var `roomRecord`: kotlin.Boolean + , + var `roomAdmin`: kotlin.Boolean + , + var `roomJoin`: kotlin.Boolean + , + var `room`: kotlin.String + , + var `destinationRoom`: kotlin.String + , + var `canPublish`: kotlin.Boolean + , + var `canSubscribe`: kotlin.Boolean + , + var `canPublishData`: kotlin.Boolean + , + var `canPublishSources`: List + , + var `canUpdateOwnMetadata`: kotlin.Boolean + , + var `ingressAdmin`: kotlin.Boolean + , + var `hidden`: kotlin.Boolean + , + var `recorder`: kotlin.Boolean + +){ + + + + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypeVideoGrants: FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): VideoGrants { + return VideoGrants( + FfiConverterBoolean.read(buf), + FfiConverterBoolean.read(buf), + FfiConverterBoolean.read(buf), + FfiConverterBoolean.read(buf), + FfiConverterBoolean.read(buf), + FfiConverterString.read(buf), + FfiConverterString.read(buf), + FfiConverterBoolean.read(buf), + FfiConverterBoolean.read(buf), + FfiConverterBoolean.read(buf), + FfiConverterSequenceString.read(buf), + FfiConverterBoolean.read(buf), + FfiConverterBoolean.read(buf), + FfiConverterBoolean.read(buf), + FfiConverterBoolean.read(buf), + ) + } + + override fun allocationSize(value: VideoGrants) = ( + FfiConverterBoolean.allocationSize(value.`roomCreate`) + + FfiConverterBoolean.allocationSize(value.`roomList`) + + FfiConverterBoolean.allocationSize(value.`roomRecord`) + + FfiConverterBoolean.allocationSize(value.`roomAdmin`) + + FfiConverterBoolean.allocationSize(value.`roomJoin`) + + FfiConverterString.allocationSize(value.`room`) + + FfiConverterString.allocationSize(value.`destinationRoom`) + + FfiConverterBoolean.allocationSize(value.`canPublish`) + + FfiConverterBoolean.allocationSize(value.`canSubscribe`) + + FfiConverterBoolean.allocationSize(value.`canPublishData`) + + FfiConverterSequenceString.allocationSize(value.`canPublishSources`) + + FfiConverterBoolean.allocationSize(value.`canUpdateOwnMetadata`) + + FfiConverterBoolean.allocationSize(value.`ingressAdmin`) + + FfiConverterBoolean.allocationSize(value.`hidden`) + + FfiConverterBoolean.allocationSize(value.`recorder`) + ) + + override fun write(value: VideoGrants, buf: ByteBuffer) { + FfiConverterBoolean.write(value.`roomCreate`, buf) + FfiConverterBoolean.write(value.`roomList`, buf) + FfiConverterBoolean.write(value.`roomRecord`, buf) + FfiConverterBoolean.write(value.`roomAdmin`, buf) + FfiConverterBoolean.write(value.`roomJoin`, buf) + FfiConverterString.write(value.`room`, buf) + FfiConverterString.write(value.`destinationRoom`, buf) + FfiConverterBoolean.write(value.`canPublish`, buf) + FfiConverterBoolean.write(value.`canSubscribe`, buf) + FfiConverterBoolean.write(value.`canPublishData`, buf) + FfiConverterSequenceString.write(value.`canPublishSources`, buf) + FfiConverterBoolean.write(value.`canUpdateOwnMetadata`, buf) + FfiConverterBoolean.write(value.`ingressAdmin`, buf) + FfiConverterBoolean.write(value.`hidden`, buf) + FfiConverterBoolean.write(value.`recorder`, buf) + } +} + + + + + +/** + * An error that can occur during token generation or verification. + */ +sealed class AccessTokenException(message: String): kotlin.Exception(message) { + + class InvalidKeys(message: String) : AccessTokenException(message) + + class InvalidEnv(message: String) : AccessTokenException(message) + + class InvalidClaims(message: String) : AccessTokenException(message) + + class Encoding(message: String) : AccessTokenException(message) + + + companion object ErrorHandler : UniffiRustCallStatusErrorHandler { + override fun lift(error_buf: RustBuffer.ByValue): AccessTokenException = FfiConverterTypeAccessTokenError.lift(error_buf) + } +} + +/** + * @suppress + */ +public object FfiConverterTypeAccessTokenError : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): AccessTokenException { + + return when(buf.getInt()) { + 1 -> AccessTokenException.InvalidKeys(FfiConverterString.read(buf)) + 2 -> AccessTokenException.InvalidEnv(FfiConverterString.read(buf)) + 3 -> AccessTokenException.InvalidClaims(FfiConverterString.read(buf)) + 4 -> AccessTokenException.Encoding(FfiConverterString.read(buf)) + else -> throw RuntimeException("invalid error enum value, something is very wrong!!") + } + + } + + override fun allocationSize(value: AccessTokenException): ULong { + return 4UL + } + + override fun write(value: AccessTokenException, buf: ByteBuffer) { + when(value) { + is AccessTokenException.InvalidKeys -> { + buf.putInt(1) + Unit + } + is AccessTokenException.InvalidEnv -> { + buf.putInt(2) + Unit + } + is AccessTokenException.InvalidClaims -> { + buf.putInt(3) + Unit + } + is AccessTokenException.Encoding -> { + buf.putInt(4) + Unit + } + }.let { /* this makes the `when` an expression, which ensures it is exhaustive */ } + } + +} + + + + +enum class LogForwardFilter { + + OFF, + ERROR, + WARN, + INFO, + DEBUG, + TRACE; + companion object +} + + +/** + * @suppress + */ +public object FfiConverterTypeLogForwardFilter: FfiConverterRustBuffer { + override fun read(buf: ByteBuffer) = try { + LogForwardFilter.values()[buf.getInt() - 1] + } catch (e: IndexOutOfBoundsException) { + throw RuntimeException("invalid enum value, something is very wrong!!", e) + } + + override fun allocationSize(value: LogForwardFilter) = 4UL + + override fun write(value: LogForwardFilter, buf: ByteBuffer) { + buf.putInt(value.ordinal + 1) + } +} + + + + + + +enum class LogForwardLevel { + + ERROR, + WARN, + INFO, + DEBUG, + TRACE; + companion object +} + + +/** + * @suppress + */ +public object FfiConverterTypeLogForwardLevel: FfiConverterRustBuffer { + override fun read(buf: ByteBuffer) = try { + LogForwardLevel.values()[buf.getInt() - 1] + } catch (e: IndexOutOfBoundsException) { + throw RuntimeException("invalid enum value, something is very wrong!!", e) + } + + override fun allocationSize(value: LogForwardLevel) = 4UL + + override fun write(value: LogForwardLevel, buf: ByteBuffer) { + buf.putInt(value.ordinal + 1) + } +} + + + + + + +/** + * @suppress + */ +public object FfiConverterOptionalUInt: FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): kotlin.UInt? { + if (buf.get().toInt() == 0) { + return null + } + return FfiConverterUInt.read(buf) + } + + override fun allocationSize(value: kotlin.UInt?): ULong { + if (value == null) { + return 1UL + } else { + return 1UL + FfiConverterUInt.allocationSize(value) + } + } + + override fun write(value: kotlin.UInt?, buf: ByteBuffer) { + if (value == null) { + buf.put(0) + } else { + buf.put(1) + FfiConverterUInt.write(value, buf) + } + } +} + + + + +/** + * @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 FfiConverterOptionalDuration: FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): java.time.Duration? { + if (buf.get().toInt() == 0) { + return null + } + return FfiConverterDuration.read(buf) + } + + override fun allocationSize(value: java.time.Duration?): ULong { + if (value == null) { + return 1UL + } else { + return 1UL + FfiConverterDuration.allocationSize(value) + } + } + + override fun write(value: java.time.Duration?, buf: ByteBuffer) { + if (value == null) { + buf.put(0) + } else { + buf.put(1) + FfiConverterDuration.write(value, buf) + } + } +} + + + + +/** + * @suppress + */ +public object FfiConverterOptionalTypeApiCredentials: FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): ApiCredentials? { + if (buf.get().toInt() == 0) { + return null + } + return FfiConverterTypeApiCredentials.read(buf) + } + + override fun allocationSize(value: ApiCredentials?): ULong { + if (value == null) { + return 1UL + } else { + return 1UL + FfiConverterTypeApiCredentials.allocationSize(value) + } + } + + override fun write(value: ApiCredentials?, buf: ByteBuffer) { + if (value == null) { + buf.put(0) + } else { + buf.put(1) + FfiConverterTypeApiCredentials.write(value, buf) + } + } +} + + + + +/** + * @suppress + */ +public object FfiConverterOptionalTypeLogForwardEntry: FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): LogForwardEntry? { + if (buf.get().toInt() == 0) { + return null + } + return FfiConverterTypeLogForwardEntry.read(buf) + } + + override fun allocationSize(value: LogForwardEntry?): ULong { + if (value == null) { + return 1UL + } else { + return 1UL + FfiConverterTypeLogForwardEntry.allocationSize(value) + } + } + + override fun write(value: LogForwardEntry?, buf: ByteBuffer) { + if (value == null) { + buf.put(0) + } else { + buf.put(1) + FfiConverterTypeLogForwardEntry.write(value, buf) + } + } +} + + + + +/** + * @suppress + */ +public object FfiConverterOptionalTypeSIPGrants: FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): SipGrants? { + if (buf.get().toInt() == 0) { + return null + } + return FfiConverterTypeSIPGrants.read(buf) + } + + override fun allocationSize(value: SipGrants?): ULong { + if (value == null) { + return 1UL + } else { + return 1UL + FfiConverterTypeSIPGrants.allocationSize(value) + } + } + + override fun write(value: SipGrants?, buf: ByteBuffer) { + if (value == null) { + buf.put(0) + } else { + buf.put(1) + FfiConverterTypeSIPGrants.write(value, buf) + } + } +} + + + + +/** + * @suppress + */ +public object FfiConverterOptionalTypeVideoGrants: FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): VideoGrants? { + if (buf.get().toInt() == 0) { + return null + } + return FfiConverterTypeVideoGrants.read(buf) + } + + override fun allocationSize(value: VideoGrants?): ULong { + if (value == null) { + return 1UL + } else { + return 1UL + FfiConverterTypeVideoGrants.allocationSize(value) + } + } + + override fun write(value: VideoGrants?, buf: ByteBuffer) { + if (value == null) { + buf.put(0) + } else { + buf.put(1) + FfiConverterTypeVideoGrants.write(value, buf) + } + } +} + + + + +/** + * @suppress + */ +public object FfiConverterOptionalMapStringString: FfiConverterRustBuffer?> { + override fun read(buf: ByteBuffer): Map? { + if (buf.get().toInt() == 0) { + return null + } + return FfiConverterMapStringString.read(buf) + } + + override fun allocationSize(value: Map?): ULong { + if (value == null) { + return 1UL + } else { + return 1UL + FfiConverterMapStringString.allocationSize(value) + } + } + + override fun write(value: Map?, buf: ByteBuffer) { + if (value == null) { + buf.put(0) + } else { + buf.put(1) + FfiConverterMapStringString.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 FfiConverterMapStringString: FfiConverterRustBuffer> { + override fun read(buf: ByteBuffer): Map { + val len = buf.getInt() + return buildMap(len) { + repeat(len) { + val k = FfiConverterString.read(buf) + val v = FfiConverterString.read(buf) + this[k] = v + } + } + } + + override fun allocationSize(value: Map): ULong { + val spaceForMapSize = 4UL + val spaceForChildren = value.map { (k, v) -> + FfiConverterString.allocationSize(k) + + FfiConverterString.allocationSize(v) + }.sum() + return spaceForMapSize + spaceForChildren + } + + override fun write(value: Map, buf: ByteBuffer) { + buf.putInt(value.size) + // The parens on `(k, v)` here ensure we're calling the right method, + // which is important for compatibility with older android devices. + // Ref https://blog.danlew.net/2017/03/16/kotlin-puzzler-whose-line-is-it-anyways/ + value.forEach { (k, v) -> + FfiConverterString.write(k, buf) + FfiConverterString.write(v, buf) + } + } +} + + + + + + + + + /** + * Returns the version specified in the crate's Cargo.toml. + */ fun `buildVersion`(): kotlin.String { + return FfiConverterString.lift( + uniffiRustCall() { _status -> + UniffiLib.uniffi_livekit_uniffi_fn_func_build_version( + + _status) +} + ) + } + + + /** + * Generates an access token. + * + * If `credentials` are omitted, API key and secret will be read from the environment + * variables `LIVEKIT_API_KEY` and `LIVEKIT_SECRET` respectively. + + */ + @Throws(AccessTokenException::class) fun `generateToken`(`options`: TokenOptions, `credentials`: ApiCredentials?): kotlin.String { + return FfiConverterString.lift( + uniffiRustCallWithError(AccessTokenException) { _status -> + UniffiLib.uniffi_livekit_uniffi_fn_func_generate_token( + + FfiConverterTypeTokenOptions.lower(`options`),FfiConverterOptionalTypeApiCredentials.lower(`credentials`),_status) +} + ) + } + + + /** + * Bootstraps log forwarding. + * + * Generally, you will invoke this once early in program execution. However, + * subsequent invocations are allowed to change the log level. + + */ fun `logForwardBootstrap`(`level`: LogForwardFilter) + = + uniffiRustCall() { _status -> + UniffiLib.uniffi_livekit_uniffi_fn_func_log_forward_bootstrap( + + FfiConverterTypeLogForwardFilter.lower(`level`),_status) +} + + + + /** + * Asynchronously receives a forwarded log entry. + * + * Invoke repeatedly to receive log entries as they are produced + * until `None` is returned, indicating forwarding has ended. Clients will + * likely want to bridge this to the languages's equivalent of an asynchronous stream. + + */ + @Suppress("ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE") + suspend fun `logForwardReceive`() : LogForwardEntry? { + return uniffiRustCallAsync( + UniffiLib.uniffi_livekit_uniffi_fn_func_log_forward_receive(), + { future, callback, continuation -> UniffiLib.ffi_livekit_uniffi_rust_future_poll_rust_buffer(future, callback, continuation) }, + { future, continuation -> UniffiLib.ffi_livekit_uniffi_rust_future_complete_rust_buffer(future, continuation) }, + { future -> UniffiLib.ffi_livekit_uniffi_rust_future_free_rust_buffer(future) }, + // lift function + { FfiConverterOptionalTypeLogForwardEntry.lift(it) }, + // Error FFI converter + UniffiNullRustCallStatusErrorHandler, + ) + } + + /** + * Verifies an access token. + * + * If `credentials` are omitted, API key and secret will be read from the environment + * variables `LIVEKIT_API_KEY` and `LIVEKIT_SECRET` respectively. + + */ + @Throws(AccessTokenException::class) fun `verifyToken`(`token`: kotlin.String, `credentials`: ApiCredentials?): Claims { + return FfiConverterTypeClaims.lift( + uniffiRustCallWithError(AccessTokenException) { _status -> + UniffiLib.uniffi_livekit_uniffi_fn_func_verify_token( + + FfiConverterString.lower(`token`),FfiConverterOptionalTypeApiCredentials.lower(`credentials`),_status) +} + ) + } + + + diff --git a/livekit-uniffi/generated/python/livekit_uniffi.py b/livekit-uniffi/generated/python/livekit_uniffi.py new file mode 100644 index 000000000..47d095205 --- /dev/null +++ b/livekit-uniffi/generated/python/livekit_uniffi.py @@ -0,0 +1,2013 @@ +# This file was autogenerated by some hot garbage in the `uniffi` crate. +# Trust me, you don't want to mess with it! + +# Common helper code. +# +# Ideally this would live in a separate .py 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 Python +# helpers directly inline like we're doing here. + +from __future__ import annotations +import os +import sys +import ctypes +from dataclasses import dataclass +import enum +import struct +import contextlib +import datetime +import threading +import itertools +import traceback +import typing +import asyncio +import platform + + +# Used for default argument values +_DEFAULT = object() # type: typing.Any + + +class _UniffiRustBuffer(ctypes.Structure): + _fields_ = [ + ("capacity", ctypes.c_uint64), + ("len", ctypes.c_uint64), + ("data", ctypes.POINTER(ctypes.c_char)), + ] + + @staticmethod + def default(): + return _UniffiRustBuffer(0, 0, None) + + @staticmethod + def alloc(size): + return _uniffi_rust_call(_UniffiLib.ffi_livekit_uniffi_rustbuffer_alloc, size) + + @staticmethod + def reserve(rbuf, additional): + return _uniffi_rust_call(_UniffiLib.ffi_livekit_uniffi_rustbuffer_reserve, rbuf, additional) + + def free(self): + return _uniffi_rust_call(_UniffiLib.ffi_livekit_uniffi_rustbuffer_free, self) + + def __str__(self): + return "_UniffiRustBuffer(capacity={}, len={}, data={})".format( + self.capacity, + self.len, + self.data[0:self.len] + ) + + @contextlib.contextmanager + def alloc_with_builder(*args): + """Context-manger to allocate a buffer using a _UniffiRustBufferBuilder. + + The allocated buffer will be automatically freed if an error occurs, ensuring that + we don't accidentally leak it. + """ + builder = _UniffiRustBufferBuilder() + try: + yield builder + except: + builder.discard() + raise + + @contextlib.contextmanager + def consume_with_stream(self): + """Context-manager to consume a buffer using a _UniffiRustBufferStream. + + The _UniffiRustBuffer will be freed once the context-manager exits, ensuring that we don't + leak it even if an error occurs. + """ + try: + s = _UniffiRustBufferStream.from_rust_buffer(self) + yield s + if s.remaining() != 0: + raise RuntimeError(f"junk data left in buffer at end of consume_with_stream {s.remaining()}") + finally: + self.free() + + @contextlib.contextmanager + def read_with_stream(self): + """Context-manager to read a buffer using a _UniffiRustBufferStream. + + This is like consume_with_stream, but doesn't free the buffer afterwards. + It should only be used with borrowed `_UniffiRustBuffer` data. + """ + s = _UniffiRustBufferStream.from_rust_buffer(self) + yield s + if s.remaining() != 0: + raise RuntimeError(f"junk data left in buffer at end of read_with_stream {s.remaining()}") + +class _UniffiForeignBytes(ctypes.Structure): + _fields_ = [ + ("len", ctypes.c_int32), + ("data", ctypes.POINTER(ctypes.c_char)), + ] + + def __str__(self): + return "_UniffiForeignBytes(len={}, data={})".format(self.len, self.data[0:self.len]) + + +class _UniffiRustBufferStream: + """ + Helper for structured reading of bytes from a _UniffiRustBuffer + """ + + def __init__(self, data, len): + self.data = data + self.len = len + self.offset = 0 + + @classmethod + def from_rust_buffer(cls, buf): + return cls(buf.data, buf.len) + + def remaining(self): + return self.len - self.offset + + def _unpack_from(self, size, format): + if self.offset + size > self.len: + raise InternalError("read past end of rust buffer") + value = struct.unpack(format, self.data[self.offset:self.offset+size])[0] + self.offset += size + return value + + def read(self, size): + if self.offset + size > self.len: + raise InternalError("read past end of rust buffer") + data = self.data[self.offset:self.offset+size] + self.offset += size + return data + + def read_i8(self): + return self._unpack_from(1, ">b") + + def read_u8(self): + return self._unpack_from(1, ">B") + + def read_i16(self): + return self._unpack_from(2, ">h") + + def read_u16(self): + return self._unpack_from(2, ">H") + + def read_i32(self): + return self._unpack_from(4, ">i") + + def read_u32(self): + return self._unpack_from(4, ">I") + + def read_i64(self): + return self._unpack_from(8, ">q") + + def read_u64(self): + return self._unpack_from(8, ">Q") + + def read_float(self): + v = self._unpack_from(4, ">f") + return v + + def read_double(self): + return self._unpack_from(8, ">d") + +class _UniffiRustBufferBuilder: + """ + Helper for structured writing of bytes into a _UniffiRustBuffer. + """ + + def __init__(self): + self.rbuf = _UniffiRustBuffer.alloc(16) + self.rbuf.len = 0 + + def finalize(self): + rbuf = self.rbuf + self.rbuf = None + return rbuf + + def discard(self): + if self.rbuf is not None: + rbuf = self.finalize() + rbuf.free() + + @contextlib.contextmanager + def _reserve(self, num_bytes): + if self.rbuf.len + num_bytes > self.rbuf.capacity: + self.rbuf = _UniffiRustBuffer.reserve(self.rbuf, num_bytes) + yield None + self.rbuf.len += num_bytes + + def _pack_into(self, size, format, value): + with self._reserve(size): + # XXX TODO: I feel like I should be able to use `struct.pack_into` here but can't figure it out. + for i, byte in enumerate(struct.pack(format, value)): + self.rbuf.data[self.rbuf.len + i] = byte + + def write(self, value): + with self._reserve(len(value)): + for i, byte in enumerate(value): + self.rbuf.data[self.rbuf.len + i] = byte + + def write_i8(self, v): + self._pack_into(1, ">b", v) + + def write_u8(self, v): + self._pack_into(1, ">B", v) + + def write_i16(self, v): + self._pack_into(2, ">h", v) + + def write_u16(self, v): + self._pack_into(2, ">H", v) + + def write_i32(self, v): + self._pack_into(4, ">i", v) + + def write_u32(self, v): + self._pack_into(4, ">I", v) + + def write_i64(self, v): + self._pack_into(8, ">q", v) + + def write_u64(self, v): + self._pack_into(8, ">Q", v) + + def write_float(self, v): + self._pack_into(4, ">f", v) + + def write_double(self, v): + self._pack_into(8, ">d", v) + + def write_c_size_t(self, v): + self._pack_into(ctypes.sizeof(ctypes.c_size_t) , "@N", v) +# 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. + +class InternalError(Exception): + pass + +class _UniffiRustCallStatus(ctypes.Structure): + """ + Error runtime. + """ + _fields_ = [ + ("code", ctypes.c_int8), + ("error_buf", _UniffiRustBuffer), + ] + + # These match the values from the uniffi::rustcalls module + CALL_SUCCESS = 0 + CALL_ERROR = 1 + CALL_UNEXPECTED_ERROR = 2 + + @staticmethod + def default(): + return _UniffiRustCallStatus(code=_UniffiRustCallStatus.CALL_SUCCESS, error_buf=_UniffiRustBuffer.default()) + + def __str__(self): + if self.code == _UniffiRustCallStatus.CALL_SUCCESS: + return "_UniffiRustCallStatus(CALL_SUCCESS)" + elif self.code == _UniffiRustCallStatus.CALL_ERROR: + return "_UniffiRustCallStatus(CALL_ERROR)" + elif self.code == _UniffiRustCallStatus.CALL_UNEXPECTED_ERROR: + return "_UniffiRustCallStatus(CALL_UNEXPECTED_ERROR)" + else: + return "_UniffiRustCallStatus()" + +def _uniffi_rust_call(fn, *args): + # Call a rust function + return _uniffi_rust_call_with_error(None, fn, *args) + +def _uniffi_rust_call_with_error(error_ffi_converter, fn, *args): + # Call a rust function and handle any errors + # + # This function is used for rust calls that return Result<> and therefore can set the CALL_ERROR status code. + # error_ffi_converter must be set to the _UniffiConverter for the error class that corresponds to the result. + call_status = _UniffiRustCallStatus.default() + + args_with_error = args + (ctypes.byref(call_status),) + result = fn(*args_with_error) + _uniffi_check_call_status(error_ffi_converter, call_status) + return result + +def _uniffi_check_call_status(error_ffi_converter, call_status): + if call_status.code == _UniffiRustCallStatus.CALL_SUCCESS: + pass + elif call_status.code == _UniffiRustCallStatus.CALL_ERROR: + if error_ffi_converter is None: + call_status.error_buf.free() + raise InternalError("_uniffi_rust_call_with_error: CALL_ERROR, but error_ffi_converter is None") + else: + raise error_ffi_converter.lift(call_status.error_buf) + elif call_status.code == _UniffiRustCallStatus.CALL_UNEXPECTED_ERROR: + # When the rust code sees a panic, it tries to construct a _UniffiRustBuffer + # with the message. But if that code panics, then it just sends back + # an empty buffer. + if call_status.error_buf.len > 0: + msg = _UniffiFfiConverterString.lift(call_status.error_buf) + else: + msg = "Unknown rust panic" + raise InternalError(msg) + else: + raise InternalError("Invalid _UniffiRustCallStatus code: {}".format( + call_status.code)) + +def _uniffi_trait_interface_call(call_status, make_call, write_return_value): + try: + return write_return_value(make_call()) + except Exception as e: + call_status.code = _UniffiRustCallStatus.CALL_UNEXPECTED_ERROR + call_status.error_buf = _UniffiFfiConverterString.lower(repr(e)) + +def _uniffi_trait_interface_call_with_error(call_status, make_call, write_return_value, error_type, lower_error): + try: + try: + return write_return_value(make_call()) + except error_type as e: + call_status.code = _UniffiRustCallStatus.CALL_ERROR + call_status.error_buf = lower_error(e) + except Exception as e: + call_status.code = _UniffiRustCallStatus.CALL_UNEXPECTED_ERROR + call_status.error_buf = _UniffiFfiConverterString.lower(repr(e)) +# Initial value and increment amount for handles. +# These ensure that Python-generated handles always have the lowest bit set +_UNIFFI_HANDLEMAP_INITIAL = 1 +_UNIFFI_HANDLEMAP_DELTA = 2 + +class _UniffiHandleMap: + """ + A map where inserting, getting and removing data is synchronized with a lock. + """ + + def __init__(self): + # type Handle = int + self._map = {} # type: Dict[Handle, Any] + self._lock = threading.Lock() + self._counter = _UNIFFI_HANDLEMAP_INITIAL + + def insert(self, obj): + with self._lock: + return self._insert(obj) + + """Low-level insert, this assumes `self._lock` is held.""" + def _insert(self, obj): + handle = self._counter + self._counter += _UNIFFI_HANDLEMAP_DELTA + self._map[handle] = obj + return handle + + def get(self, handle): + try: + with self._lock: + return self._map[handle] + except KeyError: + raise InternalError(f"_UniffiHandleMap.get: Invalid handle {handle}") + + def clone(self, handle): + try: + with self._lock: + obj = self._map[handle] + return self._insert(obj) + except KeyError: + raise InternalError(f"_UniffiHandleMap.clone: Invalid handle {handle}") + + def remove(self, handle): + try: + with self._lock: + return self._map.pop(handle) + except KeyError: + raise InternalError(f"_UniffiHandleMap.remove: Invalid handle: {handle}") + + def __len__(self): + return len(self._map) +# Types conforming to `_UniffiConverterPrimitive` pass themselves directly over the FFI. +class _UniffiConverterPrimitive: + @classmethod + def lift(cls, value): + return value + + @classmethod + def lower(cls, value): + return value + +class _UniffiConverterPrimitiveInt(_UniffiConverterPrimitive): + @classmethod + def check_lower(cls, value): + try: + value = value.__index__() + except Exception: + raise TypeError("'{}' object cannot be interpreted as an integer".format(type(value).__name__)) + if not isinstance(value, int): + raise TypeError("__index__ returned non-int (type {})".format(type(value).__name__)) + if not cls.VALUE_MIN <= value < cls.VALUE_MAX: + raise ValueError("{} requires {} <= value < {}".format(cls.CLASS_NAME, cls.VALUE_MIN, cls.VALUE_MAX)) + +class _UniffiConverterPrimitiveFloat(_UniffiConverterPrimitive): + @classmethod + def check_lower(cls, value): + try: + value = value.__float__() + except Exception: + raise TypeError("must be real number, not {}".format(type(value).__name__)) + if not isinstance(value, float): + raise TypeError("__float__ returned non-float (type {})".format(type(value).__name__)) + +# Helper class for wrapper types that will always go through a _UniffiRustBuffer. +# Classes should inherit from this and implement the `read` and `write` static methods. +class _UniffiConverterRustBuffer: + @classmethod + def lift(cls, rbuf): + with rbuf.consume_with_stream() as stream: + return cls.read(stream) + + @classmethod + def lower(cls, value): + with _UniffiRustBuffer.alloc_with_builder() as builder: + cls.write(value, builder) + return builder.finalize() + +# Contains loading, initialization code, and the FFI Function declarations. +# Define some ctypes FFI types that we use in the library + +""" +Function pointer for a Rust task, which a callback function that takes a opaque pointer +""" +_UNIFFI_RUST_TASK = ctypes.CFUNCTYPE(None, ctypes.c_void_p, ctypes.c_int8) + +def _uniffi_future_callback_t(return_type): + """ + Factory function to create callback function types for async functions + """ + return ctypes.CFUNCTYPE(None, ctypes.c_uint64, return_type, _UniffiRustCallStatus) + +def _uniffi_load_indirect(): + """ + This is how we find and load the dynamic library provided by the component. + For now we just look it up by name. + """ + if sys.platform == "darwin": + libname = "lib{}.dylib" + elif sys.platform.startswith("win"): + # As of python3.8, ctypes does not seem to search $PATH when loading DLLs. + # We could use `os.add_dll_directory` to configure the search path, but + # it doesn't feel right to mess with application-wide settings. Let's + # assume that the `.dll` is next to the `.py` file and load by full path. + libname = os.path.join( + os.path.dirname(__file__), + "{}.dll", + ) + else: + # Anything else must be an ELF platform - Linux, *BSD, Solaris/illumos + libname = "lib{}.so" + + libname = libname.format("livekit_uniffi") + path = os.path.join(os.path.dirname(__file__), libname) + lib = ctypes.cdll.LoadLibrary(path) + return lib + +def _uniffi_check_contract_api_version(lib): + # Get the bindings contract version from our ComponentInterface + bindings_contract_version = 30 + # Get the scaffolding contract version by calling the into the dylib + scaffolding_contract_version = lib.ffi_livekit_uniffi_uniffi_contract_version() + if bindings_contract_version != scaffolding_contract_version: + raise InternalError("UniFFI contract version mismatch: try cleaning and rebuilding your project") + +def _uniffi_check_api_checksums(lib): + if lib.uniffi_livekit_uniffi_checksum_func_build_version() != 45072: + raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + if lib.uniffi_livekit_uniffi_checksum_func_generate_token() != 29823: + raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + if lib.uniffi_livekit_uniffi_checksum_func_log_forward_bootstrap() != 28675: + raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + if lib.uniffi_livekit_uniffi_checksum_func_log_forward_receive() != 7863: + raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + if lib.uniffi_livekit_uniffi_checksum_func_verify_token() != 47517: + raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + +# A ctypes library to expose the extern-C FFI definitions. +# This is an implementation detail which will be called internally by the public API. + +_UniffiLib = _uniffi_load_indirect() +_UniffiLib.ffi_livekit_uniffi_rustbuffer_alloc.argtypes = ( + ctypes.c_uint64, + ctypes.POINTER(_UniffiRustCallStatus), +) +_UniffiLib.ffi_livekit_uniffi_rustbuffer_alloc.restype = _UniffiRustBuffer +_UniffiLib.ffi_livekit_uniffi_rustbuffer_from_bytes.argtypes = ( + _UniffiForeignBytes, + ctypes.POINTER(_UniffiRustCallStatus), +) +_UniffiLib.ffi_livekit_uniffi_rustbuffer_from_bytes.restype = _UniffiRustBuffer +_UniffiLib.ffi_livekit_uniffi_rustbuffer_free.argtypes = ( + _UniffiRustBuffer, + ctypes.POINTER(_UniffiRustCallStatus), +) +_UniffiLib.ffi_livekit_uniffi_rustbuffer_free.restype = None +_UniffiLib.ffi_livekit_uniffi_rustbuffer_reserve.argtypes = ( + _UniffiRustBuffer, + ctypes.c_uint64, + ctypes.POINTER(_UniffiRustCallStatus), +) +_UniffiLib.ffi_livekit_uniffi_rustbuffer_reserve.restype = _UniffiRustBuffer +_UNIFFI_RUST_FUTURE_CONTINUATION_CALLBACK = ctypes.CFUNCTYPE(None,ctypes.c_uint64,ctypes.c_int8, +) +_UNIFFI_FOREIGN_FUTURE_DROPPED_CALLBACK = ctypes.CFUNCTYPE(None,ctypes.c_uint64, +) +class _UniffiForeignFutureDroppedCallbackStruct(ctypes.Structure): + _fields_ = [ + ("handle", ctypes.c_uint64), + ("free", _UNIFFI_FOREIGN_FUTURE_DROPPED_CALLBACK), + ] +_UniffiLib.ffi_livekit_uniffi_rust_future_poll_u8.argtypes = ( + ctypes.c_uint64, + _UNIFFI_RUST_FUTURE_CONTINUATION_CALLBACK, + ctypes.c_uint64, +) +_UniffiLib.ffi_livekit_uniffi_rust_future_poll_u8.restype = None +_UniffiLib.ffi_livekit_uniffi_rust_future_cancel_u8.argtypes = ( + ctypes.c_uint64, +) +_UniffiLib.ffi_livekit_uniffi_rust_future_cancel_u8.restype = None +_UniffiLib.ffi_livekit_uniffi_rust_future_complete_u8.argtypes = ( + ctypes.c_uint64, + ctypes.POINTER(_UniffiRustCallStatus), +) +_UniffiLib.ffi_livekit_uniffi_rust_future_complete_u8.restype = ctypes.c_uint8 +_UniffiLib.ffi_livekit_uniffi_rust_future_free_u8.argtypes = ( + ctypes.c_uint64, +) +_UniffiLib.ffi_livekit_uniffi_rust_future_free_u8.restype = None +_UniffiLib.ffi_livekit_uniffi_rust_future_poll_i8.argtypes = ( + ctypes.c_uint64, + _UNIFFI_RUST_FUTURE_CONTINUATION_CALLBACK, + ctypes.c_uint64, +) +_UniffiLib.ffi_livekit_uniffi_rust_future_poll_i8.restype = None +_UniffiLib.ffi_livekit_uniffi_rust_future_cancel_i8.argtypes = ( + ctypes.c_uint64, +) +_UniffiLib.ffi_livekit_uniffi_rust_future_cancel_i8.restype = None +_UniffiLib.ffi_livekit_uniffi_rust_future_complete_i8.argtypes = ( + ctypes.c_uint64, + ctypes.POINTER(_UniffiRustCallStatus), +) +_UniffiLib.ffi_livekit_uniffi_rust_future_complete_i8.restype = ctypes.c_int8 +_UniffiLib.ffi_livekit_uniffi_rust_future_free_i8.argtypes = ( + ctypes.c_uint64, +) +_UniffiLib.ffi_livekit_uniffi_rust_future_free_i8.restype = None +_UniffiLib.ffi_livekit_uniffi_rust_future_poll_u16.argtypes = ( + ctypes.c_uint64, + _UNIFFI_RUST_FUTURE_CONTINUATION_CALLBACK, + ctypes.c_uint64, +) +_UniffiLib.ffi_livekit_uniffi_rust_future_poll_u16.restype = None +_UniffiLib.ffi_livekit_uniffi_rust_future_cancel_u16.argtypes = ( + ctypes.c_uint64, +) +_UniffiLib.ffi_livekit_uniffi_rust_future_cancel_u16.restype = None +_UniffiLib.ffi_livekit_uniffi_rust_future_complete_u16.argtypes = ( + ctypes.c_uint64, + ctypes.POINTER(_UniffiRustCallStatus), +) +_UniffiLib.ffi_livekit_uniffi_rust_future_complete_u16.restype = ctypes.c_uint16 +_UniffiLib.ffi_livekit_uniffi_rust_future_free_u16.argtypes = ( + ctypes.c_uint64, +) +_UniffiLib.ffi_livekit_uniffi_rust_future_free_u16.restype = None +_UniffiLib.ffi_livekit_uniffi_rust_future_poll_i16.argtypes = ( + ctypes.c_uint64, + _UNIFFI_RUST_FUTURE_CONTINUATION_CALLBACK, + ctypes.c_uint64, +) +_UniffiLib.ffi_livekit_uniffi_rust_future_poll_i16.restype = None +_UniffiLib.ffi_livekit_uniffi_rust_future_cancel_i16.argtypes = ( + ctypes.c_uint64, +) +_UniffiLib.ffi_livekit_uniffi_rust_future_cancel_i16.restype = None +_UniffiLib.ffi_livekit_uniffi_rust_future_complete_i16.argtypes = ( + ctypes.c_uint64, + ctypes.POINTER(_UniffiRustCallStatus), +) +_UniffiLib.ffi_livekit_uniffi_rust_future_complete_i16.restype = ctypes.c_int16 +_UniffiLib.ffi_livekit_uniffi_rust_future_free_i16.argtypes = ( + ctypes.c_uint64, +) +_UniffiLib.ffi_livekit_uniffi_rust_future_free_i16.restype = None +_UniffiLib.ffi_livekit_uniffi_rust_future_poll_u32.argtypes = ( + ctypes.c_uint64, + _UNIFFI_RUST_FUTURE_CONTINUATION_CALLBACK, + ctypes.c_uint64, +) +_UniffiLib.ffi_livekit_uniffi_rust_future_poll_u32.restype = None +_UniffiLib.ffi_livekit_uniffi_rust_future_cancel_u32.argtypes = ( + ctypes.c_uint64, +) +_UniffiLib.ffi_livekit_uniffi_rust_future_cancel_u32.restype = None +_UniffiLib.ffi_livekit_uniffi_rust_future_complete_u32.argtypes = ( + ctypes.c_uint64, + ctypes.POINTER(_UniffiRustCallStatus), +) +_UniffiLib.ffi_livekit_uniffi_rust_future_complete_u32.restype = ctypes.c_uint32 +_UniffiLib.ffi_livekit_uniffi_rust_future_free_u32.argtypes = ( + ctypes.c_uint64, +) +_UniffiLib.ffi_livekit_uniffi_rust_future_free_u32.restype = None +_UniffiLib.ffi_livekit_uniffi_rust_future_poll_i32.argtypes = ( + ctypes.c_uint64, + _UNIFFI_RUST_FUTURE_CONTINUATION_CALLBACK, + ctypes.c_uint64, +) +_UniffiLib.ffi_livekit_uniffi_rust_future_poll_i32.restype = None +_UniffiLib.ffi_livekit_uniffi_rust_future_cancel_i32.argtypes = ( + ctypes.c_uint64, +) +_UniffiLib.ffi_livekit_uniffi_rust_future_cancel_i32.restype = None +_UniffiLib.ffi_livekit_uniffi_rust_future_complete_i32.argtypes = ( + ctypes.c_uint64, + ctypes.POINTER(_UniffiRustCallStatus), +) +_UniffiLib.ffi_livekit_uniffi_rust_future_complete_i32.restype = ctypes.c_int32 +_UniffiLib.ffi_livekit_uniffi_rust_future_free_i32.argtypes = ( + ctypes.c_uint64, +) +_UniffiLib.ffi_livekit_uniffi_rust_future_free_i32.restype = None +_UniffiLib.ffi_livekit_uniffi_rust_future_poll_u64.argtypes = ( + ctypes.c_uint64, + _UNIFFI_RUST_FUTURE_CONTINUATION_CALLBACK, + ctypes.c_uint64, +) +_UniffiLib.ffi_livekit_uniffi_rust_future_poll_u64.restype = None +_UniffiLib.ffi_livekit_uniffi_rust_future_cancel_u64.argtypes = ( + ctypes.c_uint64, +) +_UniffiLib.ffi_livekit_uniffi_rust_future_cancel_u64.restype = None +_UniffiLib.ffi_livekit_uniffi_rust_future_complete_u64.argtypes = ( + ctypes.c_uint64, + ctypes.POINTER(_UniffiRustCallStatus), +) +_UniffiLib.ffi_livekit_uniffi_rust_future_complete_u64.restype = ctypes.c_uint64 +_UniffiLib.ffi_livekit_uniffi_rust_future_free_u64.argtypes = ( + ctypes.c_uint64, +) +_UniffiLib.ffi_livekit_uniffi_rust_future_free_u64.restype = None +_UniffiLib.ffi_livekit_uniffi_rust_future_poll_i64.argtypes = ( + ctypes.c_uint64, + _UNIFFI_RUST_FUTURE_CONTINUATION_CALLBACK, + ctypes.c_uint64, +) +_UniffiLib.ffi_livekit_uniffi_rust_future_poll_i64.restype = None +_UniffiLib.ffi_livekit_uniffi_rust_future_cancel_i64.argtypes = ( + ctypes.c_uint64, +) +_UniffiLib.ffi_livekit_uniffi_rust_future_cancel_i64.restype = None +_UniffiLib.ffi_livekit_uniffi_rust_future_complete_i64.argtypes = ( + ctypes.c_uint64, + ctypes.POINTER(_UniffiRustCallStatus), +) +_UniffiLib.ffi_livekit_uniffi_rust_future_complete_i64.restype = ctypes.c_int64 +_UniffiLib.ffi_livekit_uniffi_rust_future_free_i64.argtypes = ( + ctypes.c_uint64, +) +_UniffiLib.ffi_livekit_uniffi_rust_future_free_i64.restype = None +_UniffiLib.ffi_livekit_uniffi_rust_future_poll_f32.argtypes = ( + ctypes.c_uint64, + _UNIFFI_RUST_FUTURE_CONTINUATION_CALLBACK, + ctypes.c_uint64, +) +_UniffiLib.ffi_livekit_uniffi_rust_future_poll_f32.restype = None +_UniffiLib.ffi_livekit_uniffi_rust_future_cancel_f32.argtypes = ( + ctypes.c_uint64, +) +_UniffiLib.ffi_livekit_uniffi_rust_future_cancel_f32.restype = None +_UniffiLib.ffi_livekit_uniffi_rust_future_complete_f32.argtypes = ( + ctypes.c_uint64, + ctypes.POINTER(_UniffiRustCallStatus), +) +_UniffiLib.ffi_livekit_uniffi_rust_future_complete_f32.restype = ctypes.c_float +_UniffiLib.ffi_livekit_uniffi_rust_future_free_f32.argtypes = ( + ctypes.c_uint64, +) +_UniffiLib.ffi_livekit_uniffi_rust_future_free_f32.restype = None +_UniffiLib.ffi_livekit_uniffi_rust_future_poll_f64.argtypes = ( + ctypes.c_uint64, + _UNIFFI_RUST_FUTURE_CONTINUATION_CALLBACK, + ctypes.c_uint64, +) +_UniffiLib.ffi_livekit_uniffi_rust_future_poll_f64.restype = None +_UniffiLib.ffi_livekit_uniffi_rust_future_cancel_f64.argtypes = ( + ctypes.c_uint64, +) +_UniffiLib.ffi_livekit_uniffi_rust_future_cancel_f64.restype = None +_UniffiLib.ffi_livekit_uniffi_rust_future_complete_f64.argtypes = ( + ctypes.c_uint64, + ctypes.POINTER(_UniffiRustCallStatus), +) +_UniffiLib.ffi_livekit_uniffi_rust_future_complete_f64.restype = ctypes.c_double +_UniffiLib.ffi_livekit_uniffi_rust_future_free_f64.argtypes = ( + ctypes.c_uint64, +) +_UniffiLib.ffi_livekit_uniffi_rust_future_free_f64.restype = None +_UniffiLib.ffi_livekit_uniffi_rust_future_poll_rust_buffer.argtypes = ( + ctypes.c_uint64, + _UNIFFI_RUST_FUTURE_CONTINUATION_CALLBACK, + ctypes.c_uint64, +) +_UniffiLib.ffi_livekit_uniffi_rust_future_poll_rust_buffer.restype = None +_UniffiLib.ffi_livekit_uniffi_rust_future_cancel_rust_buffer.argtypes = ( + ctypes.c_uint64, +) +_UniffiLib.ffi_livekit_uniffi_rust_future_cancel_rust_buffer.restype = None +_UniffiLib.ffi_livekit_uniffi_rust_future_complete_rust_buffer.argtypes = ( + ctypes.c_uint64, + ctypes.POINTER(_UniffiRustCallStatus), +) +_UniffiLib.ffi_livekit_uniffi_rust_future_complete_rust_buffer.restype = _UniffiRustBuffer +_UniffiLib.ffi_livekit_uniffi_rust_future_free_rust_buffer.argtypes = ( + ctypes.c_uint64, +) +_UniffiLib.ffi_livekit_uniffi_rust_future_free_rust_buffer.restype = None +_UniffiLib.ffi_livekit_uniffi_rust_future_poll_void.argtypes = ( + ctypes.c_uint64, + _UNIFFI_RUST_FUTURE_CONTINUATION_CALLBACK, + ctypes.c_uint64, +) +_UniffiLib.ffi_livekit_uniffi_rust_future_poll_void.restype = None +_UniffiLib.ffi_livekit_uniffi_rust_future_cancel_void.argtypes = ( + ctypes.c_uint64, +) +_UniffiLib.ffi_livekit_uniffi_rust_future_cancel_void.restype = None +_UniffiLib.ffi_livekit_uniffi_rust_future_complete_void.argtypes = ( + ctypes.c_uint64, + ctypes.POINTER(_UniffiRustCallStatus), +) +_UniffiLib.ffi_livekit_uniffi_rust_future_complete_void.restype = None +_UniffiLib.ffi_livekit_uniffi_rust_future_free_void.argtypes = ( + ctypes.c_uint64, +) +_UniffiLib.ffi_livekit_uniffi_rust_future_free_void.restype = None +_UniffiLib.uniffi_livekit_uniffi_fn_func_build_version.argtypes = ( + ctypes.POINTER(_UniffiRustCallStatus), +) +_UniffiLib.uniffi_livekit_uniffi_fn_func_build_version.restype = _UniffiRustBuffer +_UniffiLib.uniffi_livekit_uniffi_fn_func_generate_token.argtypes = ( + _UniffiRustBuffer, + _UniffiRustBuffer, + ctypes.POINTER(_UniffiRustCallStatus), +) +_UniffiLib.uniffi_livekit_uniffi_fn_func_generate_token.restype = _UniffiRustBuffer +_UniffiLib.uniffi_livekit_uniffi_fn_func_log_forward_bootstrap.argtypes = ( + _UniffiRustBuffer, + ctypes.POINTER(_UniffiRustCallStatus), +) +_UniffiLib.uniffi_livekit_uniffi_fn_func_log_forward_bootstrap.restype = None +_UniffiLib.uniffi_livekit_uniffi_fn_func_log_forward_receive.argtypes = ( +) +_UniffiLib.uniffi_livekit_uniffi_fn_func_log_forward_receive.restype = ctypes.c_uint64 +_UniffiLib.uniffi_livekit_uniffi_fn_func_verify_token.argtypes = ( + _UniffiRustBuffer, + _UniffiRustBuffer, + ctypes.POINTER(_UniffiRustCallStatus), +) +_UniffiLib.uniffi_livekit_uniffi_fn_func_verify_token.restype = _UniffiRustBuffer +_UniffiLib.ffi_livekit_uniffi_uniffi_contract_version.argtypes = ( +) +_UniffiLib.ffi_livekit_uniffi_uniffi_contract_version.restype = ctypes.c_uint32 +_UniffiLib.uniffi_livekit_uniffi_checksum_func_build_version.argtypes = ( +) +_UniffiLib.uniffi_livekit_uniffi_checksum_func_build_version.restype = ctypes.c_uint16 +_UniffiLib.uniffi_livekit_uniffi_checksum_func_generate_token.argtypes = ( +) +_UniffiLib.uniffi_livekit_uniffi_checksum_func_generate_token.restype = ctypes.c_uint16 +_UniffiLib.uniffi_livekit_uniffi_checksum_func_log_forward_bootstrap.argtypes = ( +) +_UniffiLib.uniffi_livekit_uniffi_checksum_func_log_forward_bootstrap.restype = ctypes.c_uint16 +_UniffiLib.uniffi_livekit_uniffi_checksum_func_log_forward_receive.argtypes = ( +) +_UniffiLib.uniffi_livekit_uniffi_checksum_func_log_forward_receive.restype = ctypes.c_uint16 +_UniffiLib.uniffi_livekit_uniffi_checksum_func_verify_token.argtypes = ( +) +_UniffiLib.uniffi_livekit_uniffi_checksum_func_verify_token.restype = ctypes.c_uint16 + +_uniffi_check_contract_api_version(_UniffiLib) +# _uniffi_check_api_checksums(_UniffiLib) + +# RustFuturePoll values +_UNIFFI_RUST_FUTURE_POLL_READY = 0 +_UNIFFI_RUST_FUTURE_POLL_WAKE = 1 + +# Stores futures for _uniffi_continuation_callback +_UniffiContinuationHandleMap = _UniffiHandleMap() + +_UNIFFI_GLOBAL_EVENT_LOOP = None + +""" +Set the event loop to use for async functions + +This is needed if some async functions run outside of the eventloop, for example: + - A non-eventloop thread is spawned, maybe from `EventLoop.run_in_executor` or maybe from the + Rust code spawning its own thread. + - The Rust code calls an async callback method from a sync callback function, using something + like `pollster` to block on the async call. + +In this case, we need an event loop to run the Python async function, but there's no eventloop set +for the thread. Use `uniffi_set_event_loop` to force an eventloop to be used in this case. +""" +def uniffi_set_event_loop(eventloop: asyncio.BaseEventLoop): + global _UNIFFI_GLOBAL_EVENT_LOOP + _UNIFFI_GLOBAL_EVENT_LOOP = eventloop + +def _uniffi_get_event_loop(): + if _UNIFFI_GLOBAL_EVENT_LOOP is not None: + return _UNIFFI_GLOBAL_EVENT_LOOP + else: + return asyncio.get_running_loop() + +# Continuation callback for async functions +# lift the return value or error and resolve the future, causing the async function to resume. +@_UNIFFI_RUST_FUTURE_CONTINUATION_CALLBACK +def _uniffi_continuation_callback(future_ptr, poll_code): + (eventloop, future) = _UniffiContinuationHandleMap.remove(future_ptr) + eventloop.call_soon_threadsafe(_uniffi_set_future_result, future, poll_code) + +def _uniffi_set_future_result(future, poll_code): + if not future.cancelled(): + future.set_result(poll_code) + +async def _uniffi_rust_call_async(rust_future, ffi_poll, ffi_complete, ffi_free, lift_func, error_ffi_converter): + try: + eventloop = _uniffi_get_event_loop() + + # Loop and poll until we see a _UNIFFI_RUST_FUTURE_POLL_READY value + while True: + future = eventloop.create_future() + ffi_poll( + rust_future, + _uniffi_continuation_callback, + _UniffiContinuationHandleMap.insert((eventloop, future)), + ) + poll_code = await future + if poll_code == _UNIFFI_RUST_FUTURE_POLL_READY: + break + + return lift_func( + _uniffi_rust_call_with_error(error_ffi_converter, ffi_complete, rust_future) + ) + finally: + ffi_free(rust_future) + +# Public interface members begin here. + + +class _UniffiFfiConverterString: + @staticmethod + def check_lower(value): + if not isinstance(value, str): + raise TypeError("argument must be str, not {}".format(type(value).__name__)) + return value + + @staticmethod + def read(buf): + size = buf.read_i32() + if size < 0: + raise InternalError("Unexpected negative string length") + utf8_bytes = buf.read(size) + return utf8_bytes.decode("utf-8") + + @staticmethod + def write(value, buf): + utf8_bytes = value.encode("utf-8") + buf.write_i32(len(utf8_bytes)) + buf.write(utf8_bytes) + + @staticmethod + def lift(buf): + with buf.consume_with_stream() as stream: + return stream.read(stream.remaining()).decode("utf-8") + + @staticmethod + def lower(value): + with _UniffiRustBuffer.alloc_with_builder() as builder: + builder.write(value.encode("utf-8")) + return builder.finalize() + +@dataclass +class ApiCredentials: + """ + API credentials for access token generation and verification. +""" + def __init__(self, *, key:str, secret:str): + self.key = key + self.secret = secret + + + + + def __str__(self): + return "ApiCredentials(key={}, secret={})".format(self.key, self.secret) + def __eq__(self, other): + if self.key != other.key: + return False + if self.secret != other.secret: + return False + return True + +class _UniffiFfiConverterTypeApiCredentials(_UniffiConverterRustBuffer): + @staticmethod + def read(buf): + return ApiCredentials( + key=_UniffiFfiConverterString.read(buf), + secret=_UniffiFfiConverterString.read(buf), + ) + + @staticmethod + def check_lower(value): + _UniffiFfiConverterString.check_lower(value.key) + _UniffiFfiConverterString.check_lower(value.secret) + + @staticmethod + def write(value, buf): + _UniffiFfiConverterString.write(value.key, buf) + _UniffiFfiConverterString.write(value.secret, buf) + +class _UniffiFfiConverterUInt64(_UniffiConverterPrimitiveInt): + CLASS_NAME = "u64" + VALUE_MIN = 0 + VALUE_MAX = 2**64 + + @staticmethod + def read(buf): + return buf.read_u64() + + @staticmethod + def write(value, buf): + buf.write_u64(value) + +class _UniffiFfiConverterBoolean: + @classmethod + def check_lower(cls, value): + return not not value + + @classmethod + def lower(cls, value): + return 1 if value else 0 + + @staticmethod + def lift(value): + return value != 0 + + @classmethod + def read(cls, buf): + return cls.lift(buf.read_u8()) + + @classmethod + def write(cls, value, buf): + buf.write_u8(value) + +class _UniffiFfiConverterSequenceString(_UniffiConverterRustBuffer): + @classmethod + def check_lower(cls, value): + for item in value: + _UniffiFfiConverterString.check_lower(item) + + @classmethod + def write(cls, value, buf): + items = len(value) + buf.write_i32(items) + for item in value: + _UniffiFfiConverterString.write(item, buf) + + @classmethod + def read(cls, buf): + count = buf.read_i32() + if count < 0: + raise InternalError("Unexpected negative sequence length") + + return [ + _UniffiFfiConverterString.read(buf) for i in range(count) + ] + +@dataclass +class VideoGrants: + """ + Room permissions + + Maps to the JWT's `video` field. +""" + def __init__(self, *, room_create:bool, room_list:bool, room_record:bool, room_admin:bool, room_join:bool, room:str, destination_room:str, can_publish:bool, can_subscribe:bool, can_publish_data:bool, can_publish_sources:typing.List[str], can_update_own_metadata:bool, ingress_admin:bool, hidden:bool, recorder:bool): + self.room_create = room_create + self.room_list = room_list + self.room_record = room_record + self.room_admin = room_admin + self.room_join = room_join + self.room = room + self.destination_room = destination_room + self.can_publish = can_publish + self.can_subscribe = can_subscribe + self.can_publish_data = can_publish_data + self.can_publish_sources = can_publish_sources + self.can_update_own_metadata = can_update_own_metadata + self.ingress_admin = ingress_admin + self.hidden = hidden + self.recorder = recorder + + + + + def __str__(self): + return "VideoGrants(room_create={}, room_list={}, room_record={}, room_admin={}, room_join={}, room={}, destination_room={}, can_publish={}, can_subscribe={}, can_publish_data={}, can_publish_sources={}, can_update_own_metadata={}, ingress_admin={}, hidden={}, recorder={})".format(self.room_create, self.room_list, self.room_record, self.room_admin, self.room_join, self.room, self.destination_room, self.can_publish, self.can_subscribe, self.can_publish_data, self.can_publish_sources, self.can_update_own_metadata, self.ingress_admin, self.hidden, self.recorder) + def __eq__(self, other): + if self.room_create != other.room_create: + return False + if self.room_list != other.room_list: + return False + if self.room_record != other.room_record: + return False + if self.room_admin != other.room_admin: + return False + if self.room_join != other.room_join: + return False + if self.room != other.room: + return False + if self.destination_room != other.destination_room: + return False + if self.can_publish != other.can_publish: + return False + if self.can_subscribe != other.can_subscribe: + return False + if self.can_publish_data != other.can_publish_data: + return False + if self.can_publish_sources != other.can_publish_sources: + return False + if self.can_update_own_metadata != other.can_update_own_metadata: + return False + if self.ingress_admin != other.ingress_admin: + return False + if self.hidden != other.hidden: + return False + if self.recorder != other.recorder: + return False + return True + +class _UniffiFfiConverterTypeVideoGrants(_UniffiConverterRustBuffer): + @staticmethod + def read(buf): + return VideoGrants( + room_create=_UniffiFfiConverterBoolean.read(buf), + room_list=_UniffiFfiConverterBoolean.read(buf), + room_record=_UniffiFfiConverterBoolean.read(buf), + room_admin=_UniffiFfiConverterBoolean.read(buf), + room_join=_UniffiFfiConverterBoolean.read(buf), + room=_UniffiFfiConverterString.read(buf), + destination_room=_UniffiFfiConverterString.read(buf), + can_publish=_UniffiFfiConverterBoolean.read(buf), + can_subscribe=_UniffiFfiConverterBoolean.read(buf), + can_publish_data=_UniffiFfiConverterBoolean.read(buf), + can_publish_sources=_UniffiFfiConverterSequenceString.read(buf), + can_update_own_metadata=_UniffiFfiConverterBoolean.read(buf), + ingress_admin=_UniffiFfiConverterBoolean.read(buf), + hidden=_UniffiFfiConverterBoolean.read(buf), + recorder=_UniffiFfiConverterBoolean.read(buf), + ) + + @staticmethod + def check_lower(value): + _UniffiFfiConverterBoolean.check_lower(value.room_create) + _UniffiFfiConverterBoolean.check_lower(value.room_list) + _UniffiFfiConverterBoolean.check_lower(value.room_record) + _UniffiFfiConverterBoolean.check_lower(value.room_admin) + _UniffiFfiConverterBoolean.check_lower(value.room_join) + _UniffiFfiConverterString.check_lower(value.room) + _UniffiFfiConverterString.check_lower(value.destination_room) + _UniffiFfiConverterBoolean.check_lower(value.can_publish) + _UniffiFfiConverterBoolean.check_lower(value.can_subscribe) + _UniffiFfiConverterBoolean.check_lower(value.can_publish_data) + _UniffiFfiConverterSequenceString.check_lower(value.can_publish_sources) + _UniffiFfiConverterBoolean.check_lower(value.can_update_own_metadata) + _UniffiFfiConverterBoolean.check_lower(value.ingress_admin) + _UniffiFfiConverterBoolean.check_lower(value.hidden) + _UniffiFfiConverterBoolean.check_lower(value.recorder) + + @staticmethod + def write(value, buf): + _UniffiFfiConverterBoolean.write(value.room_create, buf) + _UniffiFfiConverterBoolean.write(value.room_list, buf) + _UniffiFfiConverterBoolean.write(value.room_record, buf) + _UniffiFfiConverterBoolean.write(value.room_admin, buf) + _UniffiFfiConverterBoolean.write(value.room_join, buf) + _UniffiFfiConverterString.write(value.room, buf) + _UniffiFfiConverterString.write(value.destination_room, buf) + _UniffiFfiConverterBoolean.write(value.can_publish, buf) + _UniffiFfiConverterBoolean.write(value.can_subscribe, buf) + _UniffiFfiConverterBoolean.write(value.can_publish_data, buf) + _UniffiFfiConverterSequenceString.write(value.can_publish_sources, buf) + _UniffiFfiConverterBoolean.write(value.can_update_own_metadata, buf) + _UniffiFfiConverterBoolean.write(value.ingress_admin, buf) + _UniffiFfiConverterBoolean.write(value.hidden, buf) + _UniffiFfiConverterBoolean.write(value.recorder, buf) + +@dataclass +class SipGrants: + """ + SIP grants + + Maps to the JWT's `sip` field. + +""" + def __init__(self, *, admin:bool, call:bool): + self.admin = admin + self.call = call + + + + + def __str__(self): + return "SipGrants(admin={}, call={})".format(self.admin, self.call) + def __eq__(self, other): + if self.admin != other.admin: + return False + if self.call != other.call: + return False + return True + +class _UniffiFfiConverterTypeSIPGrants(_UniffiConverterRustBuffer): + @staticmethod + def read(buf): + return SipGrants( + admin=_UniffiFfiConverterBoolean.read(buf), + call=_UniffiFfiConverterBoolean.read(buf), + ) + + @staticmethod + def check_lower(value): + _UniffiFfiConverterBoolean.check_lower(value.admin) + _UniffiFfiConverterBoolean.check_lower(value.call) + + @staticmethod + def write(value, buf): + _UniffiFfiConverterBoolean.write(value.admin, buf) + _UniffiFfiConverterBoolean.write(value.call, buf) + +class _UniffiFfiConverterMapStringString(_UniffiConverterRustBuffer): + @classmethod + def check_lower(cls, items): + for (key, value) in items.items(): + _UniffiFfiConverterString.check_lower(key) + _UniffiFfiConverterString.check_lower(value) + + @classmethod + def write(cls, items, buf): + buf.write_i32(len(items)) + for (key, value) in items.items(): + _UniffiFfiConverterString.write(key, buf) + _UniffiFfiConverterString.write(value, buf) + + @classmethod + def read(cls, buf): + count = buf.read_i32() + if count < 0: + raise InternalError("Unexpected negative map size") + + # It would be nice to use a dict comprehension, + # but in Python 3.7 and before the evaluation order is not according to spec, + # so we we're reading the value before the key. + # This loop makes the order explicit: first reading the key, then the value. + d = {} + for i in range(count): + key = _UniffiFfiConverterString.read(buf) + val = _UniffiFfiConverterString.read(buf) + d[key] = val + return d + +@dataclass +class Claims: + """ + Claims decoded from a valid access token. +""" + def __init__(self, *, exp:int, iss:str, nbf:int, sub:str, name:str, video:VideoGrants, sip:SipGrants, sha256:str, metadata:str, attributes:dict[str, str], room_name:str): + self.exp = exp + self.iss = iss + self.nbf = nbf + self.sub = sub + self.name = name + self.video = video + self.sip = sip + self.sha256 = sha256 + self.metadata = metadata + self.attributes = attributes + self.room_name = room_name + + + + + def __str__(self): + return "Claims(exp={}, iss={}, nbf={}, sub={}, name={}, video={}, sip={}, sha256={}, metadata={}, attributes={}, room_name={})".format(self.exp, self.iss, self.nbf, self.sub, self.name, self.video, self.sip, self.sha256, self.metadata, self.attributes, self.room_name) + def __eq__(self, other): + if self.exp != other.exp: + return False + if self.iss != other.iss: + return False + if self.nbf != other.nbf: + return False + if self.sub != other.sub: + return False + if self.name != other.name: + return False + if self.video != other.video: + return False + if self.sip != other.sip: + return False + if self.sha256 != other.sha256: + return False + if self.metadata != other.metadata: + return False + if self.attributes != other.attributes: + return False + if self.room_name != other.room_name: + return False + return True + +class _UniffiFfiConverterTypeClaims(_UniffiConverterRustBuffer): + @staticmethod + def read(buf): + return Claims( + exp=_UniffiFfiConverterUInt64.read(buf), + iss=_UniffiFfiConverterString.read(buf), + nbf=_UniffiFfiConverterUInt64.read(buf), + sub=_UniffiFfiConverterString.read(buf), + name=_UniffiFfiConverterString.read(buf), + video=_UniffiFfiConverterTypeVideoGrants.read(buf), + sip=_UniffiFfiConverterTypeSIPGrants.read(buf), + sha256=_UniffiFfiConverterString.read(buf), + metadata=_UniffiFfiConverterString.read(buf), + attributes=_UniffiFfiConverterMapStringString.read(buf), + room_name=_UniffiFfiConverterString.read(buf), + ) + + @staticmethod + def check_lower(value): + _UniffiFfiConverterUInt64.check_lower(value.exp) + _UniffiFfiConverterString.check_lower(value.iss) + _UniffiFfiConverterUInt64.check_lower(value.nbf) + _UniffiFfiConverterString.check_lower(value.sub) + _UniffiFfiConverterString.check_lower(value.name) + _UniffiFfiConverterTypeVideoGrants.check_lower(value.video) + _UniffiFfiConverterTypeSIPGrants.check_lower(value.sip) + _UniffiFfiConverterString.check_lower(value.sha256) + _UniffiFfiConverterString.check_lower(value.metadata) + _UniffiFfiConverterMapStringString.check_lower(value.attributes) + _UniffiFfiConverterString.check_lower(value.room_name) + + @staticmethod + def write(value, buf): + _UniffiFfiConverterUInt64.write(value.exp, buf) + _UniffiFfiConverterString.write(value.iss, buf) + _UniffiFfiConverterUInt64.write(value.nbf, buf) + _UniffiFfiConverterString.write(value.sub, buf) + _UniffiFfiConverterString.write(value.name, buf) + _UniffiFfiConverterTypeVideoGrants.write(value.video, buf) + _UniffiFfiConverterTypeSIPGrants.write(value.sip, buf) + _UniffiFfiConverterString.write(value.sha256, buf) + _UniffiFfiConverterString.write(value.metadata, buf) + _UniffiFfiConverterMapStringString.write(value.attributes, buf) + _UniffiFfiConverterString.write(value.room_name, buf) + + + + + + +class LogForwardLevel(enum.Enum): + + ERROR = 0 + + WARN = 1 + + INFO = 2 + + DEBUG = 3 + + TRACE = 4 + + + +class _UniffiFfiConverterTypeLogForwardLevel(_UniffiConverterRustBuffer): + @staticmethod + def read(buf): + variant = buf.read_i32() + if variant == 1: + return LogForwardLevel.ERROR + if variant == 2: + return LogForwardLevel.WARN + if variant == 3: + return LogForwardLevel.INFO + if variant == 4: + return LogForwardLevel.DEBUG + if variant == 5: + return LogForwardLevel.TRACE + raise InternalError("Raw enum value doesn't match any cases") + + @staticmethod + def check_lower(value): + if value == LogForwardLevel.ERROR: + return + if value == LogForwardLevel.WARN: + return + if value == LogForwardLevel.INFO: + return + if value == LogForwardLevel.DEBUG: + return + if value == LogForwardLevel.TRACE: + return + raise ValueError(value) + + @staticmethod + def write(value, buf): + if value == LogForwardLevel.ERROR: + buf.write_i32(1) + if value == LogForwardLevel.WARN: + buf.write_i32(2) + if value == LogForwardLevel.INFO: + buf.write_i32(3) + if value == LogForwardLevel.DEBUG: + buf.write_i32(4) + if value == LogForwardLevel.TRACE: + buf.write_i32(5) + + + +class _UniffiFfiConverterOptionalString(_UniffiConverterRustBuffer): + @classmethod + def check_lower(cls, value): + if value is not None: + _UniffiFfiConverterString.check_lower(value) + + @classmethod + def write(cls, value, buf): + if value is None: + buf.write_u8(0) + return + + buf.write_u8(1) + _UniffiFfiConverterString.write(value, buf) + + @classmethod + def read(cls, buf): + flag = buf.read_u8() + if flag == 0: + return None + elif flag == 1: + return _UniffiFfiConverterString.read(buf) + else: + raise InternalError("Unexpected flag byte for optional type") + +class _UniffiFfiConverterUInt32(_UniffiConverterPrimitiveInt): + CLASS_NAME = "u32" + VALUE_MIN = 0 + VALUE_MAX = 2**32 + + @staticmethod + def read(buf): + return buf.read_u32() + + @staticmethod + def write(value, buf): + buf.write_u32(value) + +class _UniffiFfiConverterOptionalUInt32(_UniffiConverterRustBuffer): + @classmethod + def check_lower(cls, value): + if value is not None: + _UniffiFfiConverterUInt32.check_lower(value) + + @classmethod + def write(cls, value, buf): + if value is None: + buf.write_u8(0) + return + + buf.write_u8(1) + _UniffiFfiConverterUInt32.write(value, buf) + + @classmethod + def read(cls, buf): + flag = buf.read_u8() + if flag == 0: + return None + elif flag == 1: + return _UniffiFfiConverterUInt32.read(buf) + else: + raise InternalError("Unexpected flag byte for optional type") + +@dataclass +class LogForwardEntry: + def __init__(self, *, level:LogForwardLevel, target:str, file:typing.Optional[str], line:typing.Optional[int], message:str): + self.level = level + self.target = target + self.file = file + self.line = line + self.message = message + + + + + def __str__(self): + return "LogForwardEntry(level={}, target={}, file={}, line={}, message={})".format(self.level, self.target, self.file, self.line, self.message) + def __eq__(self, other): + if self.level != other.level: + return False + if self.target != other.target: + return False + if self.file != other.file: + return False + if self.line != other.line: + return False + if self.message != other.message: + return False + return True + +class _UniffiFfiConverterTypeLogForwardEntry(_UniffiConverterRustBuffer): + @staticmethod + def read(buf): + return LogForwardEntry( + level=_UniffiFfiConverterTypeLogForwardLevel.read(buf), + target=_UniffiFfiConverterString.read(buf), + file=_UniffiFfiConverterOptionalString.read(buf), + line=_UniffiFfiConverterOptionalUInt32.read(buf), + message=_UniffiFfiConverterString.read(buf), + ) + + @staticmethod + def check_lower(value): + _UniffiFfiConverterTypeLogForwardLevel.check_lower(value.level) + _UniffiFfiConverterString.check_lower(value.target) + _UniffiFfiConverterOptionalString.check_lower(value.file) + _UniffiFfiConverterOptionalUInt32.check_lower(value.line) + _UniffiFfiConverterString.check_lower(value.message) + + @staticmethod + def write(value, buf): + _UniffiFfiConverterTypeLogForwardLevel.write(value.level, buf) + _UniffiFfiConverterString.write(value.target, buf) + _UniffiFfiConverterOptionalString.write(value.file, buf) + _UniffiFfiConverterOptionalUInt32.write(value.line, buf) + _UniffiFfiConverterString.write(value.message, buf) + +# The Duration type. +Duration = datetime.timedelta + +# There is a loss of precision when converting from Rust durations, +# which are accurate to the nanosecond, +# to Python durations, which are only accurate to the microsecond. +class _UniffiFfiConverterDuration(_UniffiConverterRustBuffer): + @staticmethod + def read(buf): + seconds = buf.read_u64() + microseconds = buf.read_u32() / 1.0e3 + return datetime.timedelta(seconds=seconds, microseconds=microseconds) + + @staticmethod + def check_lower(value): + seconds = value.seconds + value.days * 24 * 3600 + if seconds < 0: + raise ValueError("Invalid duration, must be non-negative") + + @staticmethod + def write(value, buf): + seconds = value.seconds + value.days * 24 * 3600 + nanoseconds = value.microseconds * 1000 + buf.write_i64(seconds) + buf.write_u32(nanoseconds) + +class _UniffiFfiConverterOptionalDuration(_UniffiConverterRustBuffer): + @classmethod + def check_lower(cls, value): + if value is not None: + _UniffiFfiConverterDuration.check_lower(value) + + @classmethod + def write(cls, value, buf): + if value is None: + buf.write_u8(0) + return + + buf.write_u8(1) + _UniffiFfiConverterDuration.write(value, buf) + + @classmethod + def read(cls, buf): + flag = buf.read_u8() + if flag == 0: + return None + elif flag == 1: + return _UniffiFfiConverterDuration.read(buf) + else: + raise InternalError("Unexpected flag byte for optional type") + +class _UniffiFfiConverterOptionalTypeVideoGrants(_UniffiConverterRustBuffer): + @classmethod + def check_lower(cls, value): + if value is not None: + _UniffiFfiConverterTypeVideoGrants.check_lower(value) + + @classmethod + def write(cls, value, buf): + if value is None: + buf.write_u8(0) + return + + buf.write_u8(1) + _UniffiFfiConverterTypeVideoGrants.write(value, buf) + + @classmethod + def read(cls, buf): + flag = buf.read_u8() + if flag == 0: + return None + elif flag == 1: + return _UniffiFfiConverterTypeVideoGrants.read(buf) + else: + raise InternalError("Unexpected flag byte for optional type") + +class _UniffiFfiConverterOptionalTypeSIPGrants(_UniffiConverterRustBuffer): + @classmethod + def check_lower(cls, value): + if value is not None: + _UniffiFfiConverterTypeSIPGrants.check_lower(value) + + @classmethod + def write(cls, value, buf): + if value is None: + buf.write_u8(0) + return + + buf.write_u8(1) + _UniffiFfiConverterTypeSIPGrants.write(value, buf) + + @classmethod + def read(cls, buf): + flag = buf.read_u8() + if flag == 0: + return None + elif flag == 1: + return _UniffiFfiConverterTypeSIPGrants.read(buf) + else: + raise InternalError("Unexpected flag byte for optional type") + +class _UniffiFfiConverterOptionalMapStringString(_UniffiConverterRustBuffer): + @classmethod + def check_lower(cls, value): + if value is not None: + _UniffiFfiConverterMapStringString.check_lower(value) + + @classmethod + def write(cls, value, buf): + if value is None: + buf.write_u8(0) + return + + buf.write_u8(1) + _UniffiFfiConverterMapStringString.write(value, buf) + + @classmethod + def read(cls, buf): + flag = buf.read_u8() + if flag == 0: + return None + elif flag == 1: + return _UniffiFfiConverterMapStringString.read(buf) + else: + raise InternalError("Unexpected flag byte for optional type") + +@dataclass +class TokenOptions: + """ + Options used for generating an access token. + + Any fields left empty will use the token generator's defaults. + +""" + def __init__(self, *, ttl:typing.Optional[Duration] = None, video_grants:typing.Optional[VideoGrants] = None, sip_grants:typing.Optional[SipGrants] = None, identity:typing.Optional[str] = None, name:typing.Optional[str] = None, metadata:typing.Optional[str] = None, attributes:typing.Optional[dict[str, str]] = None, sha256:typing.Optional[str] = None, room_name:typing.Optional[str] = None): + self.ttl = ttl + self.video_grants = video_grants + self.sip_grants = sip_grants + self.identity = identity + self.name = name + self.metadata = metadata + self.attributes = attributes + self.sha256 = sha256 + self.room_name = room_name + + + + + def __str__(self): + return "TokenOptions(ttl={}, video_grants={}, sip_grants={}, identity={}, name={}, metadata={}, attributes={}, sha256={}, room_name={})".format(self.ttl, self.video_grants, self.sip_grants, self.identity, self.name, self.metadata, self.attributes, self.sha256, self.room_name) + def __eq__(self, other): + if self.ttl != other.ttl: + return False + if self.video_grants != other.video_grants: + return False + if self.sip_grants != other.sip_grants: + return False + if self.identity != other.identity: + return False + if self.name != other.name: + return False + if self.metadata != other.metadata: + return False + if self.attributes != other.attributes: + return False + if self.sha256 != other.sha256: + return False + if self.room_name != other.room_name: + return False + return True + +class _UniffiFfiConverterTypeTokenOptions(_UniffiConverterRustBuffer): + @staticmethod + def read(buf): + return TokenOptions( + ttl=_UniffiFfiConverterOptionalDuration.read(buf), + video_grants=_UniffiFfiConverterOptionalTypeVideoGrants.read(buf), + sip_grants=_UniffiFfiConverterOptionalTypeSIPGrants.read(buf), + identity=_UniffiFfiConverterOptionalString.read(buf), + name=_UniffiFfiConverterOptionalString.read(buf), + metadata=_UniffiFfiConverterOptionalString.read(buf), + attributes=_UniffiFfiConverterOptionalMapStringString.read(buf), + sha256=_UniffiFfiConverterOptionalString.read(buf), + room_name=_UniffiFfiConverterOptionalString.read(buf), + ) + + @staticmethod + def check_lower(value): + _UniffiFfiConverterOptionalDuration.check_lower(value.ttl) + _UniffiFfiConverterOptionalTypeVideoGrants.check_lower(value.video_grants) + _UniffiFfiConverterOptionalTypeSIPGrants.check_lower(value.sip_grants) + _UniffiFfiConverterOptionalString.check_lower(value.identity) + _UniffiFfiConverterOptionalString.check_lower(value.name) + _UniffiFfiConverterOptionalString.check_lower(value.metadata) + _UniffiFfiConverterOptionalMapStringString.check_lower(value.attributes) + _UniffiFfiConverterOptionalString.check_lower(value.sha256) + _UniffiFfiConverterOptionalString.check_lower(value.room_name) + + @staticmethod + def write(value, buf): + _UniffiFfiConverterOptionalDuration.write(value.ttl, buf) + _UniffiFfiConverterOptionalTypeVideoGrants.write(value.video_grants, buf) + _UniffiFfiConverterOptionalTypeSIPGrants.write(value.sip_grants, buf) + _UniffiFfiConverterOptionalString.write(value.identity, buf) + _UniffiFfiConverterOptionalString.write(value.name, buf) + _UniffiFfiConverterOptionalString.write(value.metadata, buf) + _UniffiFfiConverterOptionalMapStringString.write(value.attributes, buf) + _UniffiFfiConverterOptionalString.write(value.sha256, buf) + _UniffiFfiConverterOptionalString.write(value.room_name, buf) + + + +# AccessTokenError +# We want to define each variant as a nested class that's also a subclass, +# which is tricky in Python. To accomplish this we're going to create each +# class separately, then manually add the child classes to the base class's +# __dict__. All of this happens in dummy class to avoid polluting the module +# namespace. +class AccessTokenError(Exception): + """ + An error that can occur during token generation or verification. +""" + pass + +_UniffiTempAccessTokenError = AccessTokenError + +class AccessTokenError: # type: ignore + """ + An error that can occur during token generation or verification. +""" + + class InvalidKeys(_UniffiTempAccessTokenError): + def __repr__(self): + return "AccessTokenError.InvalidKeys({})".format(repr(str(self))) + _UniffiTempAccessTokenError.InvalidKeys = InvalidKeys # type: ignore + class InvalidEnv(_UniffiTempAccessTokenError): + def __repr__(self): + return "AccessTokenError.InvalidEnv({})".format(repr(str(self))) + _UniffiTempAccessTokenError.InvalidEnv = InvalidEnv # type: ignore + class InvalidClaims(_UniffiTempAccessTokenError): + def __repr__(self): + return "AccessTokenError.InvalidClaims({})".format(repr(str(self))) + _UniffiTempAccessTokenError.InvalidClaims = InvalidClaims # type: ignore + class Encoding(_UniffiTempAccessTokenError): + def __repr__(self): + return "AccessTokenError.Encoding({})".format(repr(str(self))) + _UniffiTempAccessTokenError.Encoding = Encoding # type: ignore + +AccessTokenError = _UniffiTempAccessTokenError # type: ignore +del _UniffiTempAccessTokenError + + +class _UniffiFfiConverterTypeAccessTokenError(_UniffiConverterRustBuffer): + @staticmethod + def read(buf): + variant = buf.read_i32() + if variant == 1: + return AccessTokenError.InvalidKeys( + _UniffiFfiConverterString.read(buf), + ) + if variant == 2: + return AccessTokenError.InvalidEnv( + _UniffiFfiConverterString.read(buf), + ) + if variant == 3: + return AccessTokenError.InvalidClaims( + _UniffiFfiConverterString.read(buf), + ) + if variant == 4: + return AccessTokenError.Encoding( + _UniffiFfiConverterString.read(buf), + ) + raise InternalError("Raw enum value doesn't match any cases") + + @staticmethod + def check_lower(value): + if isinstance(value, AccessTokenError.InvalidKeys): + return + if isinstance(value, AccessTokenError.InvalidEnv): + return + if isinstance(value, AccessTokenError.InvalidClaims): + return + if isinstance(value, AccessTokenError.Encoding): + return + + @staticmethod + def write(value, buf): + if isinstance(value, AccessTokenError.InvalidKeys): + buf.write_i32(1) + if isinstance(value, AccessTokenError.InvalidEnv): + buf.write_i32(2) + if isinstance(value, AccessTokenError.InvalidClaims): + buf.write_i32(3) + if isinstance(value, AccessTokenError.Encoding): + buf.write_i32(4) + + + + + + +class LogForwardFilter(enum.Enum): + + OFF = 0 + + ERROR = 1 + + WARN = 2 + + INFO = 3 + + DEBUG = 4 + + TRACE = 5 + + + +class _UniffiFfiConverterTypeLogForwardFilter(_UniffiConverterRustBuffer): + @staticmethod + def read(buf): + variant = buf.read_i32() + if variant == 1: + return LogForwardFilter.OFF + if variant == 2: + return LogForwardFilter.ERROR + if variant == 3: + return LogForwardFilter.WARN + if variant == 4: + return LogForwardFilter.INFO + if variant == 5: + return LogForwardFilter.DEBUG + if variant == 6: + return LogForwardFilter.TRACE + raise InternalError("Raw enum value doesn't match any cases") + + @staticmethod + def check_lower(value): + if value == LogForwardFilter.OFF: + return + if value == LogForwardFilter.ERROR: + return + if value == LogForwardFilter.WARN: + return + if value == LogForwardFilter.INFO: + return + if value == LogForwardFilter.DEBUG: + return + if value == LogForwardFilter.TRACE: + return + raise ValueError(value) + + @staticmethod + def write(value, buf): + if value == LogForwardFilter.OFF: + buf.write_i32(1) + if value == LogForwardFilter.ERROR: + buf.write_i32(2) + if value == LogForwardFilter.WARN: + buf.write_i32(3) + if value == LogForwardFilter.INFO: + buf.write_i32(4) + if value == LogForwardFilter.DEBUG: + buf.write_i32(5) + if value == LogForwardFilter.TRACE: + buf.write_i32(6) + + + +class _UniffiFfiConverterOptionalTypeApiCredentials(_UniffiConverterRustBuffer): + @classmethod + def check_lower(cls, value): + if value is not None: + _UniffiFfiConverterTypeApiCredentials.check_lower(value) + + @classmethod + def write(cls, value, buf): + if value is None: + buf.write_u8(0) + return + + buf.write_u8(1) + _UniffiFfiConverterTypeApiCredentials.write(value, buf) + + @classmethod + def read(cls, buf): + flag = buf.read_u8() + if flag == 0: + return None + elif flag == 1: + return _UniffiFfiConverterTypeApiCredentials.read(buf) + else: + raise InternalError("Unexpected flag byte for optional type") + +class _UniffiFfiConverterOptionalTypeLogForwardEntry(_UniffiConverterRustBuffer): + @classmethod + def check_lower(cls, value): + if value is not None: + _UniffiFfiConverterTypeLogForwardEntry.check_lower(value) + + @classmethod + def write(cls, value, buf): + if value is None: + buf.write_u8(0) + return + + buf.write_u8(1) + _UniffiFfiConverterTypeLogForwardEntry.write(value, buf) + + @classmethod + def read(cls, buf): + flag = buf.read_u8() + if flag == 0: + return None + elif flag == 1: + return _UniffiFfiConverterTypeLogForwardEntry.read(buf) + else: + raise InternalError("Unexpected flag byte for optional type") + +class _UniffiFfiConverterUInt8(_UniffiConverterPrimitiveInt): + CLASS_NAME = "u8" + VALUE_MIN = 0 + VALUE_MAX = 2**8 + + @staticmethod + def read(buf): + return buf.read_u8() + + @staticmethod + def write(value, buf): + buf.write_u8(value) +def build_version() -> str: + """ + Returns the version specified in the crate's Cargo.toml. +""" + _uniffi_lowered_args = ( + ) + _uniffi_lift_return = _UniffiFfiConverterString.lift + _uniffi_error_converter = None + _uniffi_ffi_result = _uniffi_rust_call_with_error( + _uniffi_error_converter, + _UniffiLib.uniffi_livekit_uniffi_fn_func_build_version, + *_uniffi_lowered_args, + ) + return _uniffi_lift_return(_uniffi_ffi_result) +def generate_token(options: TokenOptions,credentials: typing.Optional[ApiCredentials]) -> str: + """ + Generates an access token. + + If `credentials` are omitted, API key and secret will be read from the environment + variables `LIVEKIT_API_KEY` and `LIVEKIT_SECRET` respectively. + +""" + + _UniffiFfiConverterTypeTokenOptions.check_lower(options) + + _UniffiFfiConverterOptionalTypeApiCredentials.check_lower(credentials) + _uniffi_lowered_args = ( + _UniffiFfiConverterTypeTokenOptions.lower(options), + _UniffiFfiConverterOptionalTypeApiCredentials.lower(credentials), + ) + _uniffi_lift_return = _UniffiFfiConverterString.lift + _uniffi_error_converter = _UniffiFfiConverterTypeAccessTokenError + _uniffi_ffi_result = _uniffi_rust_call_with_error( + _uniffi_error_converter, + _UniffiLib.uniffi_livekit_uniffi_fn_func_generate_token, + *_uniffi_lowered_args, + ) + return _uniffi_lift_return(_uniffi_ffi_result) +def log_forward_bootstrap(level: LogForwardFilter) -> None: + """ + Bootstraps log forwarding. + + Generally, you will invoke this once early in program execution. However, + subsequent invocations are allowed to change the log level. + +""" + + _UniffiFfiConverterTypeLogForwardFilter.check_lower(level) + _uniffi_lowered_args = ( + _UniffiFfiConverterTypeLogForwardFilter.lower(level), + ) + _uniffi_lift_return = lambda val: None + _uniffi_error_converter = None + _uniffi_ffi_result = _uniffi_rust_call_with_error( + _uniffi_error_converter, + _UniffiLib.uniffi_livekit_uniffi_fn_func_log_forward_bootstrap, + *_uniffi_lowered_args, + ) + return _uniffi_lift_return(_uniffi_ffi_result) +async def log_forward_receive() -> typing.Optional[LogForwardEntry]: + """ + Asynchronously receives a forwarded log entry. + + Invoke repeatedly to receive log entries as they are produced + until `None` is returned, indicating forwarding has ended. Clients will + likely want to bridge this to the languages's equivalent of an asynchronous stream. + +""" + _uniffi_lowered_args = ( + ) + _uniffi_lift_return = _UniffiFfiConverterOptionalTypeLogForwardEntry.lift + _uniffi_error_converter = None + return await _uniffi_rust_call_async( + _UniffiLib.uniffi_livekit_uniffi_fn_func_log_forward_receive(*_uniffi_lowered_args), + _UniffiLib.ffi_livekit_uniffi_rust_future_poll_rust_buffer, + _UniffiLib.ffi_livekit_uniffi_rust_future_complete_rust_buffer, + _UniffiLib.ffi_livekit_uniffi_rust_future_free_rust_buffer, + _uniffi_lift_return, + _uniffi_error_converter, + ) +def verify_token(token: str,credentials: typing.Optional[ApiCredentials]) -> Claims: + """ + Verifies an access token. + + If `credentials` are omitted, API key and secret will be read from the environment + variables `LIVEKIT_API_KEY` and `LIVEKIT_SECRET` respectively. + +""" + + _UniffiFfiConverterString.check_lower(token) + + _UniffiFfiConverterOptionalTypeApiCredentials.check_lower(credentials) + _uniffi_lowered_args = ( + _UniffiFfiConverterString.lower(token), + _UniffiFfiConverterOptionalTypeApiCredentials.lower(credentials), + ) + _uniffi_lift_return = _UniffiFfiConverterTypeClaims.lift + _uniffi_error_converter = _UniffiFfiConverterTypeAccessTokenError + _uniffi_ffi_result = _uniffi_rust_call_with_error( + _uniffi_error_converter, + _UniffiLib.uniffi_livekit_uniffi_fn_func_verify_token, + *_uniffi_lowered_args, + ) + return _uniffi_lift_return(_uniffi_ffi_result) + +__all__ = [ + "InternalError", + "LogForwardLevel", + "AccessTokenError", + "LogForwardFilter", + "ApiCredentials", + "VideoGrants", + "SipGrants", + "Claims", + "LogForwardEntry", + "TokenOptions", + "build_version", + "generate_token", + "log_forward_bootstrap", + "log_forward_receive", + "verify_token", +] \ No newline at end of file diff --git a/livekit-uniffi/generated/swift/livekit_uniffi.swift b/livekit-uniffi/generated/swift/livekit_uniffi.swift new file mode 100644 index 000000000..f41ad488e --- /dev/null +++ b/livekit-uniffi/generated/swift/livekit_uniffi.swift @@ -0,0 +1,1698 @@ +// 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(livekit_uniffiFFI) +import livekit_uniffiFFI +#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_livekit_uniffi_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_livekit_uniffi_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 { + uniffiEnsureLivekitUniffiInitialized() + 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)) + } +} +// Initial value and increment amount for handles. +// These ensure that SWIFT handles always have the lowest bit set +fileprivate let UNIFFI_HANDLEMAP_INITIAL: UInt64 = 1 +fileprivate let UNIFFI_HANDLEMAP_DELTA: UInt64 = 2 + +fileprivate final class UniffiHandleMap: @unchecked Sendable { + // All mutation happens with this lock held, which is why we implement @unchecked Sendable. + private let lock = NSLock() + private var map: [UInt64: T] = [:] + private var currentHandle: UInt64 = UNIFFI_HANDLEMAP_INITIAL + + func insert(obj: T) -> UInt64 { + lock.withLock { + return doInsert(obj) + } + } + + // Low-level insert function, this assumes `lock` is held. + private func doInsert(_ obj: T) -> UInt64 { + let handle = currentHandle + currentHandle += UNIFFI_HANDLEMAP_DELTA + 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 + } + } + + func clone(handle: UInt64) throws -> UInt64 { + try lock.withLock { + guard let obj = map[handle] else { + throw UniffiInternalError.unexpectedStaleHandle + } + return doInsert(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 FfiConverterUInt32: FfiConverterPrimitive { + typealias FfiType = UInt32 + typealias SwiftType = UInt32 + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> UInt32 { + 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 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) + } +} + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +fileprivate struct FfiConverterDuration: FfiConverterRustBuffer { + typealias SwiftType = TimeInterval + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> TimeInterval { + let seconds: UInt64 = try readInt(&buf) + let nanoseconds: UInt32 = try readInt(&buf) + return Double(seconds) + (Double(nanoseconds) / 1.0e9) + } + + public static func write(_ value: TimeInterval, into buf: inout [UInt8]) { + if value.rounded(.down) > Double(Int64.max) { + fatalError("Duration overflow, exceeds max bounds supported by Uniffi") + } + + if value < 0 { + fatalError("Invalid duration, must be non-negative") + } + + let seconds = UInt64(value) + let nanoseconds = UInt32((value - Double(seconds)) * 1.0e9) + writeInt(&buf, seconds) + writeInt(&buf, nanoseconds) + } +} + + +/** + * API credentials for access token generation and verification. + */ +public struct ApiCredentials: Equatable, Hashable { + public var key: String + public var secret: String + + // Default memberwise initializers are never public by default, so we + // declare one manually. + public init(key: String, secret: String) { + self.key = key + self.secret = secret + } + + +} + +#if compiler(>=6) +extension ApiCredentials: Sendable {} +#endif + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +public struct FfiConverterTypeApiCredentials: FfiConverterRustBuffer { + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> ApiCredentials { + return + try ApiCredentials( + key: FfiConverterString.read(from: &buf), + secret: FfiConverterString.read(from: &buf) + ) + } + + public static func write(_ value: ApiCredentials, into buf: inout [UInt8]) { + FfiConverterString.write(value.key, into: &buf) + FfiConverterString.write(value.secret, into: &buf) + } +} + + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +public func FfiConverterTypeApiCredentials_lift(_ buf: RustBuffer) throws -> ApiCredentials { + return try FfiConverterTypeApiCredentials.lift(buf) +} + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +public func FfiConverterTypeApiCredentials_lower(_ value: ApiCredentials) -> RustBuffer { + return FfiConverterTypeApiCredentials.lower(value) +} + + +/** + * Claims decoded from a valid access token. + */ +public struct Claims: Equatable, Hashable { + public var exp: UInt64 + public var iss: String + public var nbf: UInt64 + public var sub: String + public var name: String + public var video: VideoGrants + public var sip: SipGrants + public var sha256: String + public var metadata: String + public var attributes: [String: String] + public var roomName: String + + // Default memberwise initializers are never public by default, so we + // declare one manually. + public init(exp: UInt64, iss: String, nbf: UInt64, sub: String, name: String, video: VideoGrants, sip: SipGrants, sha256: String, metadata: String, attributes: [String: String], roomName: String) { + self.exp = exp + self.iss = iss + self.nbf = nbf + self.sub = sub + self.name = name + self.video = video + self.sip = sip + self.sha256 = sha256 + self.metadata = metadata + self.attributes = attributes + self.roomName = roomName + } + + +} + +#if compiler(>=6) +extension Claims: Sendable {} +#endif + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +public struct FfiConverterTypeClaims: FfiConverterRustBuffer { + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> Claims { + return + try Claims( + exp: FfiConverterUInt64.read(from: &buf), + iss: FfiConverterString.read(from: &buf), + nbf: FfiConverterUInt64.read(from: &buf), + sub: FfiConverterString.read(from: &buf), + name: FfiConverterString.read(from: &buf), + video: FfiConverterTypeVideoGrants.read(from: &buf), + sip: FfiConverterTypeSIPGrants.read(from: &buf), + sha256: FfiConverterString.read(from: &buf), + metadata: FfiConverterString.read(from: &buf), + attributes: FfiConverterDictionaryStringString.read(from: &buf), + roomName: FfiConverterString.read(from: &buf) + ) + } + + public static func write(_ value: Claims, into buf: inout [UInt8]) { + FfiConverterUInt64.write(value.exp, into: &buf) + FfiConverterString.write(value.iss, into: &buf) + FfiConverterUInt64.write(value.nbf, into: &buf) + FfiConverterString.write(value.sub, into: &buf) + FfiConverterString.write(value.name, into: &buf) + FfiConverterTypeVideoGrants.write(value.video, into: &buf) + FfiConverterTypeSIPGrants.write(value.sip, into: &buf) + FfiConverterString.write(value.sha256, into: &buf) + FfiConverterString.write(value.metadata, into: &buf) + FfiConverterDictionaryStringString.write(value.attributes, into: &buf) + FfiConverterString.write(value.roomName, into: &buf) + } +} + + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +public func FfiConverterTypeClaims_lift(_ buf: RustBuffer) throws -> Claims { + return try FfiConverterTypeClaims.lift(buf) +} + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +public func FfiConverterTypeClaims_lower(_ value: Claims) -> RustBuffer { + return FfiConverterTypeClaims.lower(value) +} + + +public struct LogForwardEntry: Equatable, Hashable { + public var level: LogForwardLevel + public var target: String + public var file: String? + public var line: UInt32? + public var message: String + + // Default memberwise initializers are never public by default, so we + // declare one manually. + public init(level: LogForwardLevel, target: String, file: String?, line: UInt32?, message: String) { + self.level = level + self.target = target + self.file = file + self.line = line + self.message = message + } + + +} + +#if compiler(>=6) +extension LogForwardEntry: Sendable {} +#endif + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +public struct FfiConverterTypeLogForwardEntry: FfiConverterRustBuffer { + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> LogForwardEntry { + return + try LogForwardEntry( + level: FfiConverterTypeLogForwardLevel.read(from: &buf), + target: FfiConverterString.read(from: &buf), + file: FfiConverterOptionString.read(from: &buf), + line: FfiConverterOptionUInt32.read(from: &buf), + message: FfiConverterString.read(from: &buf) + ) + } + + public static func write(_ value: LogForwardEntry, into buf: inout [UInt8]) { + FfiConverterTypeLogForwardLevel.write(value.level, into: &buf) + FfiConverterString.write(value.target, into: &buf) + FfiConverterOptionString.write(value.file, into: &buf) + FfiConverterOptionUInt32.write(value.line, into: &buf) + FfiConverterString.write(value.message, into: &buf) + } +} + + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +public func FfiConverterTypeLogForwardEntry_lift(_ buf: RustBuffer) throws -> LogForwardEntry { + return try FfiConverterTypeLogForwardEntry.lift(buf) +} + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +public func FfiConverterTypeLogForwardEntry_lower(_ value: LogForwardEntry) -> RustBuffer { + return FfiConverterTypeLogForwardEntry.lower(value) +} + + +/** + * SIP grants + * + * Maps to the JWT's `sip` field. + + */ +public struct SipGrants: Equatable, Hashable { + public var admin: Bool + public var call: Bool + + // Default memberwise initializers are never public by default, so we + // declare one manually. + public init(admin: Bool, call: Bool) { + self.admin = admin + self.call = call + } + + +} + +#if compiler(>=6) +extension SipGrants: Sendable {} +#endif + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +public struct FfiConverterTypeSIPGrants: FfiConverterRustBuffer { + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> SipGrants { + return + try SipGrants( + admin: FfiConverterBool.read(from: &buf), + call: FfiConverterBool.read(from: &buf) + ) + } + + public static func write(_ value: SipGrants, into buf: inout [UInt8]) { + FfiConverterBool.write(value.admin, into: &buf) + FfiConverterBool.write(value.call, into: &buf) + } +} + + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +public func FfiConverterTypeSIPGrants_lift(_ buf: RustBuffer) throws -> SipGrants { + return try FfiConverterTypeSIPGrants.lift(buf) +} + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +public func FfiConverterTypeSIPGrants_lower(_ value: SipGrants) -> RustBuffer { + return FfiConverterTypeSIPGrants.lower(value) +} + + +/** + * Options used for generating an access token. + * + * Any fields left empty will use the token generator's defaults. + + */ +public struct TokenOptions: Equatable, Hashable { + public var ttl: TimeInterval? + public var videoGrants: VideoGrants? + public var sipGrants: SipGrants? + public var identity: String? + public var name: String? + public var metadata: String? + public var attributes: [String: String]? + public var sha256: String? + public var roomName: String? + + // Default memberwise initializers are never public by default, so we + // declare one manually. + public init(ttl: TimeInterval? = nil, videoGrants: VideoGrants? = nil, sipGrants: SipGrants? = nil, identity: String? = nil, name: String? = nil, metadata: String? = nil, attributes: [String: String]? = nil, sha256: String? = nil, roomName: String? = nil) { + self.ttl = ttl + self.videoGrants = videoGrants + self.sipGrants = sipGrants + self.identity = identity + self.name = name + self.metadata = metadata + self.attributes = attributes + self.sha256 = sha256 + self.roomName = roomName + } + + +} + +#if compiler(>=6) +extension TokenOptions: Sendable {} +#endif + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +public struct FfiConverterTypeTokenOptions: FfiConverterRustBuffer { + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> TokenOptions { + return + try TokenOptions( + ttl: FfiConverterOptionDuration.read(from: &buf), + videoGrants: FfiConverterOptionTypeVideoGrants.read(from: &buf), + sipGrants: FfiConverterOptionTypeSIPGrants.read(from: &buf), + identity: FfiConverterOptionString.read(from: &buf), + name: FfiConverterOptionString.read(from: &buf), + metadata: FfiConverterOptionString.read(from: &buf), + attributes: FfiConverterOptionDictionaryStringString.read(from: &buf), + sha256: FfiConverterOptionString.read(from: &buf), + roomName: FfiConverterOptionString.read(from: &buf) + ) + } + + public static func write(_ value: TokenOptions, into buf: inout [UInt8]) { + FfiConverterOptionDuration.write(value.ttl, into: &buf) + FfiConverterOptionTypeVideoGrants.write(value.videoGrants, into: &buf) + FfiConverterOptionTypeSIPGrants.write(value.sipGrants, into: &buf) + FfiConverterOptionString.write(value.identity, into: &buf) + FfiConverterOptionString.write(value.name, into: &buf) + FfiConverterOptionString.write(value.metadata, into: &buf) + FfiConverterOptionDictionaryStringString.write(value.attributes, into: &buf) + FfiConverterOptionString.write(value.sha256, into: &buf) + FfiConverterOptionString.write(value.roomName, into: &buf) + } +} + + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +public func FfiConverterTypeTokenOptions_lift(_ buf: RustBuffer) throws -> TokenOptions { + return try FfiConverterTypeTokenOptions.lift(buf) +} + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +public func FfiConverterTypeTokenOptions_lower(_ value: TokenOptions) -> RustBuffer { + return FfiConverterTypeTokenOptions.lower(value) +} + + +/** + * Room permissions + * + * Maps to the JWT's `video` field. + */ +public struct VideoGrants: Equatable, Hashable { + public var roomCreate: Bool + public var roomList: Bool + public var roomRecord: Bool + public var roomAdmin: Bool + public var roomJoin: Bool + public var room: String + public var destinationRoom: String + public var canPublish: Bool + public var canSubscribe: Bool + public var canPublishData: Bool + public var canPublishSources: [String] + public var canUpdateOwnMetadata: Bool + public var ingressAdmin: Bool + public var hidden: Bool + public var recorder: Bool + + // Default memberwise initializers are never public by default, so we + // declare one manually. + public init(roomCreate: Bool, roomList: Bool, roomRecord: Bool, roomAdmin: Bool, roomJoin: Bool, room: String, destinationRoom: String, canPublish: Bool, canSubscribe: Bool, canPublishData: Bool, canPublishSources: [String], canUpdateOwnMetadata: Bool, ingressAdmin: Bool, hidden: Bool, recorder: Bool) { + self.roomCreate = roomCreate + self.roomList = roomList + self.roomRecord = roomRecord + self.roomAdmin = roomAdmin + self.roomJoin = roomJoin + self.room = room + self.destinationRoom = destinationRoom + self.canPublish = canPublish + self.canSubscribe = canSubscribe + self.canPublishData = canPublishData + self.canPublishSources = canPublishSources + self.canUpdateOwnMetadata = canUpdateOwnMetadata + self.ingressAdmin = ingressAdmin + self.hidden = hidden + self.recorder = recorder + } + + +} + +#if compiler(>=6) +extension VideoGrants: Sendable {} +#endif + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +public struct FfiConverterTypeVideoGrants: FfiConverterRustBuffer { + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> VideoGrants { + return + try VideoGrants( + roomCreate: FfiConverterBool.read(from: &buf), + roomList: FfiConverterBool.read(from: &buf), + roomRecord: FfiConverterBool.read(from: &buf), + roomAdmin: FfiConverterBool.read(from: &buf), + roomJoin: FfiConverterBool.read(from: &buf), + room: FfiConverterString.read(from: &buf), + destinationRoom: FfiConverterString.read(from: &buf), + canPublish: FfiConverterBool.read(from: &buf), + canSubscribe: FfiConverterBool.read(from: &buf), + canPublishData: FfiConverterBool.read(from: &buf), + canPublishSources: FfiConverterSequenceString.read(from: &buf), + canUpdateOwnMetadata: FfiConverterBool.read(from: &buf), + ingressAdmin: FfiConverterBool.read(from: &buf), + hidden: FfiConverterBool.read(from: &buf), + recorder: FfiConverterBool.read(from: &buf) + ) + } + + public static func write(_ value: VideoGrants, into buf: inout [UInt8]) { + FfiConverterBool.write(value.roomCreate, into: &buf) + FfiConverterBool.write(value.roomList, into: &buf) + FfiConverterBool.write(value.roomRecord, into: &buf) + FfiConverterBool.write(value.roomAdmin, into: &buf) + FfiConverterBool.write(value.roomJoin, into: &buf) + FfiConverterString.write(value.room, into: &buf) + FfiConverterString.write(value.destinationRoom, into: &buf) + FfiConverterBool.write(value.canPublish, into: &buf) + FfiConverterBool.write(value.canSubscribe, into: &buf) + FfiConverterBool.write(value.canPublishData, into: &buf) + FfiConverterSequenceString.write(value.canPublishSources, into: &buf) + FfiConverterBool.write(value.canUpdateOwnMetadata, into: &buf) + FfiConverterBool.write(value.ingressAdmin, into: &buf) + FfiConverterBool.write(value.hidden, into: &buf) + FfiConverterBool.write(value.recorder, into: &buf) + } +} + + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +public func FfiConverterTypeVideoGrants_lift(_ buf: RustBuffer) throws -> VideoGrants { + return try FfiConverterTypeVideoGrants.lift(buf) +} + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +public func FfiConverterTypeVideoGrants_lower(_ value: VideoGrants) -> RustBuffer { + return FfiConverterTypeVideoGrants.lower(value) +} + + +/** + * An error that can occur during token generation or verification. + */ +public enum AccessTokenError: Swift.Error, Equatable, Hashable, Foundation.LocalizedError { + + + + case InvalidKeys(message: String) + + case InvalidEnv(message: String) + + case InvalidClaims(message: String) + + case Encoding(message: String) + + + + + + public var errorDescription: String? { + String(reflecting: self) + } + +} + +#if compiler(>=6) +extension AccessTokenError: Sendable {} +#endif + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +public struct FfiConverterTypeAccessTokenError: FfiConverterRustBuffer { + typealias SwiftType = AccessTokenError + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> AccessTokenError { + let variant: Int32 = try readInt(&buf) + switch variant { + + + + + case 1: return .InvalidKeys( + message: try FfiConverterString.read(from: &buf) + ) + + case 2: return .InvalidEnv( + message: try FfiConverterString.read(from: &buf) + ) + + case 3: return .InvalidClaims( + message: try FfiConverterString.read(from: &buf) + ) + + case 4: return .Encoding( + message: try FfiConverterString.read(from: &buf) + ) + + + default: throw UniffiInternalError.unexpectedEnumCase + } + } + + public static func write(_ value: AccessTokenError, into buf: inout [UInt8]) { + switch value { + + + + + case .InvalidKeys(_ /* message is ignored*/): + writeInt(&buf, Int32(1)) + case .InvalidEnv(_ /* message is ignored*/): + writeInt(&buf, Int32(2)) + case .InvalidClaims(_ /* message is ignored*/): + writeInt(&buf, Int32(3)) + case .Encoding(_ /* message is ignored*/): + writeInt(&buf, Int32(4)) + + + } + } +} + + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +public func FfiConverterTypeAccessTokenError_lift(_ buf: RustBuffer) throws -> AccessTokenError { + return try FfiConverterTypeAccessTokenError.lift(buf) +} + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +public func FfiConverterTypeAccessTokenError_lower(_ value: AccessTokenError) -> RustBuffer { + return FfiConverterTypeAccessTokenError.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 LogForwardFilter: Equatable, Hashable { + + case off + case error + case warn + case info + case debug + case trace + + + +} + +#if compiler(>=6) +extension LogForwardFilter: Sendable {} +#endif + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +public struct FfiConverterTypeLogForwardFilter: FfiConverterRustBuffer { + typealias SwiftType = LogForwardFilter + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> LogForwardFilter { + let variant: Int32 = try readInt(&buf) + switch variant { + + case 1: return .off + + case 2: return .error + + case 3: return .warn + + case 4: return .info + + case 5: return .debug + + case 6: return .trace + + default: throw UniffiInternalError.unexpectedEnumCase + } + } + + public static func write(_ value: LogForwardFilter, into buf: inout [UInt8]) { + switch value { + + + case .off: + writeInt(&buf, Int32(1)) + + + case .error: + writeInt(&buf, Int32(2)) + + + case .warn: + writeInt(&buf, Int32(3)) + + + case .info: + writeInt(&buf, Int32(4)) + + + case .debug: + writeInt(&buf, Int32(5)) + + + case .trace: + writeInt(&buf, Int32(6)) + + } + } +} + + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +public func FfiConverterTypeLogForwardFilter_lift(_ buf: RustBuffer) throws -> LogForwardFilter { + return try FfiConverterTypeLogForwardFilter.lift(buf) +} + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +public func FfiConverterTypeLogForwardFilter_lower(_ value: LogForwardFilter) -> RustBuffer { + return FfiConverterTypeLogForwardFilter.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 LogForwardLevel: Equatable, Hashable { + + case error + case warn + case info + case debug + case trace + + + +} + +#if compiler(>=6) +extension LogForwardLevel: Sendable {} +#endif + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +public struct FfiConverterTypeLogForwardLevel: FfiConverterRustBuffer { + typealias SwiftType = LogForwardLevel + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> LogForwardLevel { + let variant: Int32 = try readInt(&buf) + switch variant { + + case 1: return .error + + case 2: return .warn + + case 3: return .info + + case 4: return .debug + + case 5: return .trace + + default: throw UniffiInternalError.unexpectedEnumCase + } + } + + public static func write(_ value: LogForwardLevel, into buf: inout [UInt8]) { + switch value { + + + case .error: + writeInt(&buf, Int32(1)) + + + case .warn: + writeInt(&buf, Int32(2)) + + + case .info: + writeInt(&buf, Int32(3)) + + + case .debug: + writeInt(&buf, Int32(4)) + + + case .trace: + writeInt(&buf, Int32(5)) + + } + } +} + + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +public func FfiConverterTypeLogForwardLevel_lift(_ buf: RustBuffer) throws -> LogForwardLevel { + return try FfiConverterTypeLogForwardLevel.lift(buf) +} + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +public func FfiConverterTypeLogForwardLevel_lower(_ value: LogForwardLevel) -> RustBuffer { + return FfiConverterTypeLogForwardLevel.lower(value) +} + + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +fileprivate struct FfiConverterOptionUInt32: FfiConverterRustBuffer { + typealias SwiftType = UInt32? + + public static func write(_ value: SwiftType, into buf: inout [UInt8]) { + guard let value = value else { + writeInt(&buf, Int8(0)) + return + } + writeInt(&buf, Int8(1)) + FfiConverterUInt32.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 FfiConverterUInt32.read(from: &buf) + default: throw UniffiInternalError.unexpectedOptionalTag + } + } +} + +#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 FfiConverterOptionDuration: FfiConverterRustBuffer { + typealias SwiftType = TimeInterval? + + public static func write(_ value: SwiftType, into buf: inout [UInt8]) { + guard let value = value else { + writeInt(&buf, Int8(0)) + return + } + writeInt(&buf, Int8(1)) + FfiConverterDuration.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 FfiConverterDuration.read(from: &buf) + default: throw UniffiInternalError.unexpectedOptionalTag + } + } +} + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +fileprivate struct FfiConverterOptionTypeApiCredentials: FfiConverterRustBuffer { + typealias SwiftType = ApiCredentials? + + public static func write(_ value: SwiftType, into buf: inout [UInt8]) { + guard let value = value else { + writeInt(&buf, Int8(0)) + return + } + writeInt(&buf, Int8(1)) + FfiConverterTypeApiCredentials.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 FfiConverterTypeApiCredentials.read(from: &buf) + default: throw UniffiInternalError.unexpectedOptionalTag + } + } +} + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +fileprivate struct FfiConverterOptionTypeLogForwardEntry: FfiConverterRustBuffer { + typealias SwiftType = LogForwardEntry? + + public static func write(_ value: SwiftType, into buf: inout [UInt8]) { + guard let value = value else { + writeInt(&buf, Int8(0)) + return + } + writeInt(&buf, Int8(1)) + FfiConverterTypeLogForwardEntry.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 FfiConverterTypeLogForwardEntry.read(from: &buf) + default: throw UniffiInternalError.unexpectedOptionalTag + } + } +} + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +fileprivate struct FfiConverterOptionTypeSIPGrants: FfiConverterRustBuffer { + typealias SwiftType = SipGrants? + + public static func write(_ value: SwiftType, into buf: inout [UInt8]) { + guard let value = value else { + writeInt(&buf, Int8(0)) + return + } + writeInt(&buf, Int8(1)) + FfiConverterTypeSIPGrants.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 FfiConverterTypeSIPGrants.read(from: &buf) + default: throw UniffiInternalError.unexpectedOptionalTag + } + } +} + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +fileprivate struct FfiConverterOptionTypeVideoGrants: FfiConverterRustBuffer { + typealias SwiftType = VideoGrants? + + public static func write(_ value: SwiftType, into buf: inout [UInt8]) { + guard let value = value else { + writeInt(&buf, Int8(0)) + return + } + writeInt(&buf, Int8(1)) + FfiConverterTypeVideoGrants.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 FfiConverterTypeVideoGrants.read(from: &buf) + default: throw UniffiInternalError.unexpectedOptionalTag + } + } +} + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +fileprivate struct FfiConverterOptionDictionaryStringString: FfiConverterRustBuffer { + typealias SwiftType = [String: 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)) + FfiConverterDictionaryStringString.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 FfiConverterDictionaryStringString.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 FfiConverterDictionaryStringString: FfiConverterRustBuffer { + public static func write(_ value: [String: String], into buf: inout [UInt8]) { + let len = Int32(value.count) + writeInt(&buf, len) + for (key, value) in value { + FfiConverterString.write(key, into: &buf) + FfiConverterString.write(value, into: &buf) + } + } + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> [String: String] { + let len: Int32 = try readInt(&buf) + var dict = [String: String]() + dict.reserveCapacity(Int(len)) + for _ in 0..>() + +fileprivate func uniffiRustCallAsync( + rustFutureFunc: () -> UInt64, + pollFunc: (UInt64, @escaping UniffiRustFutureContinuationCallback, UInt64) -> (), + completeFunc: (UInt64, UnsafeMutablePointer) -> F, + freeFunc: (UInt64) -> (), + liftFunc: (F) throws -> T, + errorHandler: ((RustBuffer) throws -> Swift.Error)? +) async throws -> T { + // Make sure to call the ensure init function since future creation doesn't have a + // RustCallStatus param, so doesn't use makeRustCall() + uniffiEnsureLivekitUniffiInitialized() + let rustFuture = rustFutureFunc() + defer { + freeFunc(rustFuture) + } + var pollResult: Int8; + repeat { + pollResult = await withUnsafeContinuation { + pollFunc( + rustFuture, + { handle, pollResult in + uniffiFutureContinuationCallback(handle: handle, pollResult: pollResult) + }, + uniffiContinuationHandleMap.insert(obj: $0) + ) + } + } while pollResult != UNIFFI_RUST_FUTURE_POLL_READY + + return try liftFunc(makeRustCall( + { completeFunc(rustFuture, $0) }, + errorHandler: errorHandler + )) +} + +// Callback handlers for an async calls. These are invoked by Rust when the future is ready. They +// lift the return value or error and resume the suspended function. +fileprivate func uniffiFutureContinuationCallback(handle: UInt64, pollResult: Int8) { + if let continuation = try? uniffiContinuationHandleMap.remove(handle: handle) { + continuation.resume(returning: pollResult) + } else { + print("uniffiFutureContinuationCallback invalid handle") + } +} +/** + * Returns the version specified in the crate's Cargo.toml. + */ +public func buildVersion() -> String { + return try! FfiConverterString.lift(try! rustCall() { + uniffi_livekit_uniffi_fn_func_build_version($0 + ) +}) +} +/** + * Generates an access token. + * + * If `credentials` are omitted, API key and secret will be read from the environment + * variables `LIVEKIT_API_KEY` and `LIVEKIT_SECRET` respectively. + + */ +public func generateToken(options: TokenOptions, credentials: ApiCredentials?)throws -> String { + return try FfiConverterString.lift(try rustCallWithError(FfiConverterTypeAccessTokenError_lift) { + uniffi_livekit_uniffi_fn_func_generate_token( + FfiConverterTypeTokenOptions_lower(options), + FfiConverterOptionTypeApiCredentials.lower(credentials),$0 + ) +}) +} +/** + * Bootstraps log forwarding. + * + * Generally, you will invoke this once early in program execution. However, + * subsequent invocations are allowed to change the log level. + + */ +public func logForwardBootstrap(level: LogForwardFilter) {try! rustCall() { + uniffi_livekit_uniffi_fn_func_log_forward_bootstrap( + FfiConverterTypeLogForwardFilter_lower(level),$0 + ) +} +} +/** + * Asynchronously receives a forwarded log entry. + * + * Invoke repeatedly to receive log entries as they are produced + * until `None` is returned, indicating forwarding has ended. Clients will + * likely want to bridge this to the languages's equivalent of an asynchronous stream. + + */ +public func logForwardReceive()async -> LogForwardEntry? { + return + try! await uniffiRustCallAsync( + rustFutureFunc: { + uniffi_livekit_uniffi_fn_func_log_forward_receive( + ) + }, + pollFunc: ffi_livekit_uniffi_rust_future_poll_rust_buffer, + completeFunc: ffi_livekit_uniffi_rust_future_complete_rust_buffer, + freeFunc: ffi_livekit_uniffi_rust_future_free_rust_buffer, + liftFunc: FfiConverterOptionTypeLogForwardEntry.lift, + errorHandler: nil + + ) +} +/** + * Verifies an access token. + * + * If `credentials` are omitted, API key and secret will be read from the environment + * variables `LIVEKIT_API_KEY` and `LIVEKIT_SECRET` respectively. + + */ +public func verifyToken(token: String, credentials: ApiCredentials?)throws -> Claims { + return try FfiConverterTypeClaims_lift(try rustCallWithError(FfiConverterTypeAccessTokenError_lift) { + uniffi_livekit_uniffi_fn_func_verify_token( + FfiConverterString.lower(token), + FfiConverterOptionTypeApiCredentials.lower(credentials),$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 let initializationResult: InitializationResult = { + // Get the bindings contract version from our ComponentInterface + let bindings_contract_version = 30 + // Get the scaffolding contract version by calling the into the dylib + let scaffolding_contract_version = ffi_livekit_uniffi_uniffi_contract_version() + if bindings_contract_version != scaffolding_contract_version { + return InitializationResult.contractVersionMismatch + } + if (uniffi_livekit_uniffi_checksum_func_build_version() != 45072) { + return InitializationResult.apiChecksumMismatch + } + if (uniffi_livekit_uniffi_checksum_func_generate_token() != 29823) { + return InitializationResult.apiChecksumMismatch + } + if (uniffi_livekit_uniffi_checksum_func_log_forward_bootstrap() != 28675) { + return InitializationResult.apiChecksumMismatch + } + if (uniffi_livekit_uniffi_checksum_func_log_forward_receive() != 7863) { + return InitializationResult.apiChecksumMismatch + } + if (uniffi_livekit_uniffi_checksum_func_verify_token() != 47517) { + return InitializationResult.apiChecksumMismatch + } + + return InitializationResult.ok +}() + +// Make the ensure init function public so that other modules which have external type references to +// our types can call it. +public func uniffiEnsureLivekitUniffiInitialized() { + 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/livekit-uniffi/generated/swift/livekit_uniffiFFI.h b/livekit-uniffi/generated/swift/livekit_uniffiFFI.h new file mode 100644 index 000000000..b7ed46438 --- /dev/null +++ b/livekit-uniffi/generated/swift/livekit_uniffiFFI.h @@ -0,0 +1,569 @@ +// 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_DROPPED_CALLBACK +#define UNIFFI_FFIDEF_FOREIGN_FUTURE_DROPPED_CALLBACK +typedef void (*UniffiForeignFutureDroppedCallback)(uint64_t + ); + +#endif +#ifndef UNIFFI_FFIDEF_CALLBACK_INTERFACE_FREE +#define UNIFFI_FFIDEF_CALLBACK_INTERFACE_FREE +typedef void (*UniffiCallbackInterfaceFree)(uint64_t + ); + +#endif +#ifndef UNIFFI_FFIDEF_CALLBACK_INTERFACE_CLONE +#define UNIFFI_FFIDEF_CALLBACK_INTERFACE_CLONE +typedef uint64_t (*UniffiCallbackInterfaceClone)(uint64_t + ); + +#endif +#ifndef UNIFFI_FFIDEF_FOREIGN_FUTURE_DROPPED_CALLBACK_STRUCT +#define UNIFFI_FFIDEF_FOREIGN_FUTURE_DROPPED_CALLBACK_STRUCT +typedef struct UniffiForeignFutureDroppedCallbackStruct { + uint64_t handle; + UniffiForeignFutureDroppedCallback _Nonnull free; +} UniffiForeignFutureDroppedCallbackStruct; + +#endif +#ifndef UNIFFI_FFIDEF_FOREIGN_FUTURE_RESULT_U8 +#define UNIFFI_FFIDEF_FOREIGN_FUTURE_RESULT_U8 +typedef struct UniffiForeignFutureResultU8 { + uint8_t returnValue; + RustCallStatus callStatus; +} UniffiForeignFutureResultU8; + +#endif +#ifndef UNIFFI_FFIDEF_FOREIGN_FUTURE_COMPLETE_U8 +#define UNIFFI_FFIDEF_FOREIGN_FUTURE_COMPLETE_U8 +typedef void (*UniffiForeignFutureCompleteU8)(uint64_t, UniffiForeignFutureResultU8 + ); + +#endif +#ifndef UNIFFI_FFIDEF_FOREIGN_FUTURE_RESULT_I8 +#define UNIFFI_FFIDEF_FOREIGN_FUTURE_RESULT_I8 +typedef struct UniffiForeignFutureResultI8 { + int8_t returnValue; + RustCallStatus callStatus; +} UniffiForeignFutureResultI8; + +#endif +#ifndef UNIFFI_FFIDEF_FOREIGN_FUTURE_COMPLETE_I8 +#define UNIFFI_FFIDEF_FOREIGN_FUTURE_COMPLETE_I8 +typedef void (*UniffiForeignFutureCompleteI8)(uint64_t, UniffiForeignFutureResultI8 + ); + +#endif +#ifndef UNIFFI_FFIDEF_FOREIGN_FUTURE_RESULT_U16 +#define UNIFFI_FFIDEF_FOREIGN_FUTURE_RESULT_U16 +typedef struct UniffiForeignFutureResultU16 { + uint16_t returnValue; + RustCallStatus callStatus; +} UniffiForeignFutureResultU16; + +#endif +#ifndef UNIFFI_FFIDEF_FOREIGN_FUTURE_COMPLETE_U16 +#define UNIFFI_FFIDEF_FOREIGN_FUTURE_COMPLETE_U16 +typedef void (*UniffiForeignFutureCompleteU16)(uint64_t, UniffiForeignFutureResultU16 + ); + +#endif +#ifndef UNIFFI_FFIDEF_FOREIGN_FUTURE_RESULT_I16 +#define UNIFFI_FFIDEF_FOREIGN_FUTURE_RESULT_I16 +typedef struct UniffiForeignFutureResultI16 { + int16_t returnValue; + RustCallStatus callStatus; +} UniffiForeignFutureResultI16; + +#endif +#ifndef UNIFFI_FFIDEF_FOREIGN_FUTURE_COMPLETE_I16 +#define UNIFFI_FFIDEF_FOREIGN_FUTURE_COMPLETE_I16 +typedef void (*UniffiForeignFutureCompleteI16)(uint64_t, UniffiForeignFutureResultI16 + ); + +#endif +#ifndef UNIFFI_FFIDEF_FOREIGN_FUTURE_RESULT_U32 +#define UNIFFI_FFIDEF_FOREIGN_FUTURE_RESULT_U32 +typedef struct UniffiForeignFutureResultU32 { + uint32_t returnValue; + RustCallStatus callStatus; +} UniffiForeignFutureResultU32; + +#endif +#ifndef UNIFFI_FFIDEF_FOREIGN_FUTURE_COMPLETE_U32 +#define UNIFFI_FFIDEF_FOREIGN_FUTURE_COMPLETE_U32 +typedef void (*UniffiForeignFutureCompleteU32)(uint64_t, UniffiForeignFutureResultU32 + ); + +#endif +#ifndef UNIFFI_FFIDEF_FOREIGN_FUTURE_RESULT_I32 +#define UNIFFI_FFIDEF_FOREIGN_FUTURE_RESULT_I32 +typedef struct UniffiForeignFutureResultI32 { + int32_t returnValue; + RustCallStatus callStatus; +} UniffiForeignFutureResultI32; + +#endif +#ifndef UNIFFI_FFIDEF_FOREIGN_FUTURE_COMPLETE_I32 +#define UNIFFI_FFIDEF_FOREIGN_FUTURE_COMPLETE_I32 +typedef void (*UniffiForeignFutureCompleteI32)(uint64_t, UniffiForeignFutureResultI32 + ); + +#endif +#ifndef UNIFFI_FFIDEF_FOREIGN_FUTURE_RESULT_U64 +#define UNIFFI_FFIDEF_FOREIGN_FUTURE_RESULT_U64 +typedef struct UniffiForeignFutureResultU64 { + uint64_t returnValue; + RustCallStatus callStatus; +} UniffiForeignFutureResultU64; + +#endif +#ifndef UNIFFI_FFIDEF_FOREIGN_FUTURE_COMPLETE_U64 +#define UNIFFI_FFIDEF_FOREIGN_FUTURE_COMPLETE_U64 +typedef void (*UniffiForeignFutureCompleteU64)(uint64_t, UniffiForeignFutureResultU64 + ); + +#endif +#ifndef UNIFFI_FFIDEF_FOREIGN_FUTURE_RESULT_I64 +#define UNIFFI_FFIDEF_FOREIGN_FUTURE_RESULT_I64 +typedef struct UniffiForeignFutureResultI64 { + int64_t returnValue; + RustCallStatus callStatus; +} UniffiForeignFutureResultI64; + +#endif +#ifndef UNIFFI_FFIDEF_FOREIGN_FUTURE_COMPLETE_I64 +#define UNIFFI_FFIDEF_FOREIGN_FUTURE_COMPLETE_I64 +typedef void (*UniffiForeignFutureCompleteI64)(uint64_t, UniffiForeignFutureResultI64 + ); + +#endif +#ifndef UNIFFI_FFIDEF_FOREIGN_FUTURE_RESULT_F32 +#define UNIFFI_FFIDEF_FOREIGN_FUTURE_RESULT_F32 +typedef struct UniffiForeignFutureResultF32 { + float returnValue; + RustCallStatus callStatus; +} UniffiForeignFutureResultF32; + +#endif +#ifndef UNIFFI_FFIDEF_FOREIGN_FUTURE_COMPLETE_F32 +#define UNIFFI_FFIDEF_FOREIGN_FUTURE_COMPLETE_F32 +typedef void (*UniffiForeignFutureCompleteF32)(uint64_t, UniffiForeignFutureResultF32 + ); + +#endif +#ifndef UNIFFI_FFIDEF_FOREIGN_FUTURE_RESULT_F64 +#define UNIFFI_FFIDEF_FOREIGN_FUTURE_RESULT_F64 +typedef struct UniffiForeignFutureResultF64 { + double returnValue; + RustCallStatus callStatus; +} UniffiForeignFutureResultF64; + +#endif +#ifndef UNIFFI_FFIDEF_FOREIGN_FUTURE_COMPLETE_F64 +#define UNIFFI_FFIDEF_FOREIGN_FUTURE_COMPLETE_F64 +typedef void (*UniffiForeignFutureCompleteF64)(uint64_t, UniffiForeignFutureResultF64 + ); + +#endif +#ifndef UNIFFI_FFIDEF_FOREIGN_FUTURE_RESULT_RUST_BUFFER +#define UNIFFI_FFIDEF_FOREIGN_FUTURE_RESULT_RUST_BUFFER +typedef struct UniffiForeignFutureResultRustBuffer { + RustBuffer returnValue; + RustCallStatus callStatus; +} UniffiForeignFutureResultRustBuffer; + +#endif +#ifndef UNIFFI_FFIDEF_FOREIGN_FUTURE_COMPLETE_RUST_BUFFER +#define UNIFFI_FFIDEF_FOREIGN_FUTURE_COMPLETE_RUST_BUFFER +typedef void (*UniffiForeignFutureCompleteRustBuffer)(uint64_t, UniffiForeignFutureResultRustBuffer + ); + +#endif +#ifndef UNIFFI_FFIDEF_FOREIGN_FUTURE_RESULT_VOID +#define UNIFFI_FFIDEF_FOREIGN_FUTURE_RESULT_VOID +typedef struct UniffiForeignFutureResultVoid { + RustCallStatus callStatus; +} UniffiForeignFutureResultVoid; + +#endif +#ifndef UNIFFI_FFIDEF_FOREIGN_FUTURE_COMPLETE_VOID +#define UNIFFI_FFIDEF_FOREIGN_FUTURE_COMPLETE_VOID +typedef void (*UniffiForeignFutureCompleteVoid)(uint64_t, UniffiForeignFutureResultVoid + ); + +#endif +#ifndef UNIFFI_FFIDEF_UNIFFI_LIVEKIT_UNIFFI_FN_FUNC_BUILD_VERSION +#define UNIFFI_FFIDEF_UNIFFI_LIVEKIT_UNIFFI_FN_FUNC_BUILD_VERSION +RustBuffer uniffi_livekit_uniffi_fn_func_build_version(RustCallStatus *_Nonnull out_status + +); +#endif +#ifndef UNIFFI_FFIDEF_UNIFFI_LIVEKIT_UNIFFI_FN_FUNC_GENERATE_TOKEN +#define UNIFFI_FFIDEF_UNIFFI_LIVEKIT_UNIFFI_FN_FUNC_GENERATE_TOKEN +RustBuffer uniffi_livekit_uniffi_fn_func_generate_token(RustBuffer options, RustBuffer credentials, RustCallStatus *_Nonnull out_status +); +#endif +#ifndef UNIFFI_FFIDEF_UNIFFI_LIVEKIT_UNIFFI_FN_FUNC_LOG_FORWARD_BOOTSTRAP +#define UNIFFI_FFIDEF_UNIFFI_LIVEKIT_UNIFFI_FN_FUNC_LOG_FORWARD_BOOTSTRAP +void uniffi_livekit_uniffi_fn_func_log_forward_bootstrap(RustBuffer level, RustCallStatus *_Nonnull out_status +); +#endif +#ifndef UNIFFI_FFIDEF_UNIFFI_LIVEKIT_UNIFFI_FN_FUNC_LOG_FORWARD_RECEIVE +#define UNIFFI_FFIDEF_UNIFFI_LIVEKIT_UNIFFI_FN_FUNC_LOG_FORWARD_RECEIVE +uint64_t uniffi_livekit_uniffi_fn_func_log_forward_receive(void + +); +#endif +#ifndef UNIFFI_FFIDEF_UNIFFI_LIVEKIT_UNIFFI_FN_FUNC_VERIFY_TOKEN +#define UNIFFI_FFIDEF_UNIFFI_LIVEKIT_UNIFFI_FN_FUNC_VERIFY_TOKEN +RustBuffer uniffi_livekit_uniffi_fn_func_verify_token(RustBuffer token, RustBuffer credentials, RustCallStatus *_Nonnull out_status +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUSTBUFFER_ALLOC +#define UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUSTBUFFER_ALLOC +RustBuffer ffi_livekit_uniffi_rustbuffer_alloc(uint64_t size, RustCallStatus *_Nonnull out_status +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUSTBUFFER_FROM_BYTES +#define UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUSTBUFFER_FROM_BYTES +RustBuffer ffi_livekit_uniffi_rustbuffer_from_bytes(ForeignBytes bytes, RustCallStatus *_Nonnull out_status +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUSTBUFFER_FREE +#define UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUSTBUFFER_FREE +void ffi_livekit_uniffi_rustbuffer_free(RustBuffer buf, RustCallStatus *_Nonnull out_status +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUSTBUFFER_RESERVE +#define UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUSTBUFFER_RESERVE +RustBuffer ffi_livekit_uniffi_rustbuffer_reserve(RustBuffer buf, uint64_t additional, RustCallStatus *_Nonnull out_status +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUST_FUTURE_POLL_U8 +#define UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUST_FUTURE_POLL_U8 +void ffi_livekit_uniffi_rust_future_poll_u8(uint64_t handle, UniffiRustFutureContinuationCallback _Nonnull callback, uint64_t callback_data +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUST_FUTURE_CANCEL_U8 +#define UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUST_FUTURE_CANCEL_U8 +void ffi_livekit_uniffi_rust_future_cancel_u8(uint64_t handle +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUST_FUTURE_FREE_U8 +#define UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUST_FUTURE_FREE_U8 +void ffi_livekit_uniffi_rust_future_free_u8(uint64_t handle +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUST_FUTURE_COMPLETE_U8 +#define UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUST_FUTURE_COMPLETE_U8 +uint8_t ffi_livekit_uniffi_rust_future_complete_u8(uint64_t handle, RustCallStatus *_Nonnull out_status +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUST_FUTURE_POLL_I8 +#define UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUST_FUTURE_POLL_I8 +void ffi_livekit_uniffi_rust_future_poll_i8(uint64_t handle, UniffiRustFutureContinuationCallback _Nonnull callback, uint64_t callback_data +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUST_FUTURE_CANCEL_I8 +#define UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUST_FUTURE_CANCEL_I8 +void ffi_livekit_uniffi_rust_future_cancel_i8(uint64_t handle +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUST_FUTURE_FREE_I8 +#define UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUST_FUTURE_FREE_I8 +void ffi_livekit_uniffi_rust_future_free_i8(uint64_t handle +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUST_FUTURE_COMPLETE_I8 +#define UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUST_FUTURE_COMPLETE_I8 +int8_t ffi_livekit_uniffi_rust_future_complete_i8(uint64_t handle, RustCallStatus *_Nonnull out_status +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUST_FUTURE_POLL_U16 +#define UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUST_FUTURE_POLL_U16 +void ffi_livekit_uniffi_rust_future_poll_u16(uint64_t handle, UniffiRustFutureContinuationCallback _Nonnull callback, uint64_t callback_data +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUST_FUTURE_CANCEL_U16 +#define UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUST_FUTURE_CANCEL_U16 +void ffi_livekit_uniffi_rust_future_cancel_u16(uint64_t handle +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUST_FUTURE_FREE_U16 +#define UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUST_FUTURE_FREE_U16 +void ffi_livekit_uniffi_rust_future_free_u16(uint64_t handle +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUST_FUTURE_COMPLETE_U16 +#define UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUST_FUTURE_COMPLETE_U16 +uint16_t ffi_livekit_uniffi_rust_future_complete_u16(uint64_t handle, RustCallStatus *_Nonnull out_status +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUST_FUTURE_POLL_I16 +#define UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUST_FUTURE_POLL_I16 +void ffi_livekit_uniffi_rust_future_poll_i16(uint64_t handle, UniffiRustFutureContinuationCallback _Nonnull callback, uint64_t callback_data +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUST_FUTURE_CANCEL_I16 +#define UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUST_FUTURE_CANCEL_I16 +void ffi_livekit_uniffi_rust_future_cancel_i16(uint64_t handle +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUST_FUTURE_FREE_I16 +#define UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUST_FUTURE_FREE_I16 +void ffi_livekit_uniffi_rust_future_free_i16(uint64_t handle +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUST_FUTURE_COMPLETE_I16 +#define UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUST_FUTURE_COMPLETE_I16 +int16_t ffi_livekit_uniffi_rust_future_complete_i16(uint64_t handle, RustCallStatus *_Nonnull out_status +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUST_FUTURE_POLL_U32 +#define UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUST_FUTURE_POLL_U32 +void ffi_livekit_uniffi_rust_future_poll_u32(uint64_t handle, UniffiRustFutureContinuationCallback _Nonnull callback, uint64_t callback_data +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUST_FUTURE_CANCEL_U32 +#define UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUST_FUTURE_CANCEL_U32 +void ffi_livekit_uniffi_rust_future_cancel_u32(uint64_t handle +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUST_FUTURE_FREE_U32 +#define UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUST_FUTURE_FREE_U32 +void ffi_livekit_uniffi_rust_future_free_u32(uint64_t handle +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUST_FUTURE_COMPLETE_U32 +#define UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUST_FUTURE_COMPLETE_U32 +uint32_t ffi_livekit_uniffi_rust_future_complete_u32(uint64_t handle, RustCallStatus *_Nonnull out_status +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUST_FUTURE_POLL_I32 +#define UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUST_FUTURE_POLL_I32 +void ffi_livekit_uniffi_rust_future_poll_i32(uint64_t handle, UniffiRustFutureContinuationCallback _Nonnull callback, uint64_t callback_data +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUST_FUTURE_CANCEL_I32 +#define UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUST_FUTURE_CANCEL_I32 +void ffi_livekit_uniffi_rust_future_cancel_i32(uint64_t handle +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUST_FUTURE_FREE_I32 +#define UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUST_FUTURE_FREE_I32 +void ffi_livekit_uniffi_rust_future_free_i32(uint64_t handle +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUST_FUTURE_COMPLETE_I32 +#define UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUST_FUTURE_COMPLETE_I32 +int32_t ffi_livekit_uniffi_rust_future_complete_i32(uint64_t handle, RustCallStatus *_Nonnull out_status +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUST_FUTURE_POLL_U64 +#define UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUST_FUTURE_POLL_U64 +void ffi_livekit_uniffi_rust_future_poll_u64(uint64_t handle, UniffiRustFutureContinuationCallback _Nonnull callback, uint64_t callback_data +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUST_FUTURE_CANCEL_U64 +#define UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUST_FUTURE_CANCEL_U64 +void ffi_livekit_uniffi_rust_future_cancel_u64(uint64_t handle +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUST_FUTURE_FREE_U64 +#define UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUST_FUTURE_FREE_U64 +void ffi_livekit_uniffi_rust_future_free_u64(uint64_t handle +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUST_FUTURE_COMPLETE_U64 +#define UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUST_FUTURE_COMPLETE_U64 +uint64_t ffi_livekit_uniffi_rust_future_complete_u64(uint64_t handle, RustCallStatus *_Nonnull out_status +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUST_FUTURE_POLL_I64 +#define UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUST_FUTURE_POLL_I64 +void ffi_livekit_uniffi_rust_future_poll_i64(uint64_t handle, UniffiRustFutureContinuationCallback _Nonnull callback, uint64_t callback_data +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUST_FUTURE_CANCEL_I64 +#define UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUST_FUTURE_CANCEL_I64 +void ffi_livekit_uniffi_rust_future_cancel_i64(uint64_t handle +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUST_FUTURE_FREE_I64 +#define UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUST_FUTURE_FREE_I64 +void ffi_livekit_uniffi_rust_future_free_i64(uint64_t handle +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUST_FUTURE_COMPLETE_I64 +#define UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUST_FUTURE_COMPLETE_I64 +int64_t ffi_livekit_uniffi_rust_future_complete_i64(uint64_t handle, RustCallStatus *_Nonnull out_status +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUST_FUTURE_POLL_F32 +#define UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUST_FUTURE_POLL_F32 +void ffi_livekit_uniffi_rust_future_poll_f32(uint64_t handle, UniffiRustFutureContinuationCallback _Nonnull callback, uint64_t callback_data +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUST_FUTURE_CANCEL_F32 +#define UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUST_FUTURE_CANCEL_F32 +void ffi_livekit_uniffi_rust_future_cancel_f32(uint64_t handle +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUST_FUTURE_FREE_F32 +#define UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUST_FUTURE_FREE_F32 +void ffi_livekit_uniffi_rust_future_free_f32(uint64_t handle +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUST_FUTURE_COMPLETE_F32 +#define UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUST_FUTURE_COMPLETE_F32 +float ffi_livekit_uniffi_rust_future_complete_f32(uint64_t handle, RustCallStatus *_Nonnull out_status +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUST_FUTURE_POLL_F64 +#define UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUST_FUTURE_POLL_F64 +void ffi_livekit_uniffi_rust_future_poll_f64(uint64_t handle, UniffiRustFutureContinuationCallback _Nonnull callback, uint64_t callback_data +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUST_FUTURE_CANCEL_F64 +#define UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUST_FUTURE_CANCEL_F64 +void ffi_livekit_uniffi_rust_future_cancel_f64(uint64_t handle +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUST_FUTURE_FREE_F64 +#define UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUST_FUTURE_FREE_F64 +void ffi_livekit_uniffi_rust_future_free_f64(uint64_t handle +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUST_FUTURE_COMPLETE_F64 +#define UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUST_FUTURE_COMPLETE_F64 +double ffi_livekit_uniffi_rust_future_complete_f64(uint64_t handle, RustCallStatus *_Nonnull out_status +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUST_FUTURE_POLL_RUST_BUFFER +#define UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUST_FUTURE_POLL_RUST_BUFFER +void ffi_livekit_uniffi_rust_future_poll_rust_buffer(uint64_t handle, UniffiRustFutureContinuationCallback _Nonnull callback, uint64_t callback_data +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUST_FUTURE_CANCEL_RUST_BUFFER +#define UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUST_FUTURE_CANCEL_RUST_BUFFER +void ffi_livekit_uniffi_rust_future_cancel_rust_buffer(uint64_t handle +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUST_FUTURE_FREE_RUST_BUFFER +#define UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUST_FUTURE_FREE_RUST_BUFFER +void ffi_livekit_uniffi_rust_future_free_rust_buffer(uint64_t handle +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUST_FUTURE_COMPLETE_RUST_BUFFER +#define UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUST_FUTURE_COMPLETE_RUST_BUFFER +RustBuffer ffi_livekit_uniffi_rust_future_complete_rust_buffer(uint64_t handle, RustCallStatus *_Nonnull out_status +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUST_FUTURE_POLL_VOID +#define UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUST_FUTURE_POLL_VOID +void ffi_livekit_uniffi_rust_future_poll_void(uint64_t handle, UniffiRustFutureContinuationCallback _Nonnull callback, uint64_t callback_data +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUST_FUTURE_CANCEL_VOID +#define UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUST_FUTURE_CANCEL_VOID +void ffi_livekit_uniffi_rust_future_cancel_void(uint64_t handle +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUST_FUTURE_FREE_VOID +#define UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUST_FUTURE_FREE_VOID +void ffi_livekit_uniffi_rust_future_free_void(uint64_t handle +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUST_FUTURE_COMPLETE_VOID +#define UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_RUST_FUTURE_COMPLETE_VOID +void ffi_livekit_uniffi_rust_future_complete_void(uint64_t handle, RustCallStatus *_Nonnull out_status +); +#endif +#ifndef UNIFFI_FFIDEF_UNIFFI_LIVEKIT_UNIFFI_CHECKSUM_FUNC_BUILD_VERSION +#define UNIFFI_FFIDEF_UNIFFI_LIVEKIT_UNIFFI_CHECKSUM_FUNC_BUILD_VERSION +uint16_t uniffi_livekit_uniffi_checksum_func_build_version(void + +); +#endif +#ifndef UNIFFI_FFIDEF_UNIFFI_LIVEKIT_UNIFFI_CHECKSUM_FUNC_GENERATE_TOKEN +#define UNIFFI_FFIDEF_UNIFFI_LIVEKIT_UNIFFI_CHECKSUM_FUNC_GENERATE_TOKEN +uint16_t uniffi_livekit_uniffi_checksum_func_generate_token(void + +); +#endif +#ifndef UNIFFI_FFIDEF_UNIFFI_LIVEKIT_UNIFFI_CHECKSUM_FUNC_LOG_FORWARD_BOOTSTRAP +#define UNIFFI_FFIDEF_UNIFFI_LIVEKIT_UNIFFI_CHECKSUM_FUNC_LOG_FORWARD_BOOTSTRAP +uint16_t uniffi_livekit_uniffi_checksum_func_log_forward_bootstrap(void + +); +#endif +#ifndef UNIFFI_FFIDEF_UNIFFI_LIVEKIT_UNIFFI_CHECKSUM_FUNC_LOG_FORWARD_RECEIVE +#define UNIFFI_FFIDEF_UNIFFI_LIVEKIT_UNIFFI_CHECKSUM_FUNC_LOG_FORWARD_RECEIVE +uint16_t uniffi_livekit_uniffi_checksum_func_log_forward_receive(void + +); +#endif +#ifndef UNIFFI_FFIDEF_UNIFFI_LIVEKIT_UNIFFI_CHECKSUM_FUNC_VERIFY_TOKEN +#define UNIFFI_FFIDEF_UNIFFI_LIVEKIT_UNIFFI_CHECKSUM_FUNC_VERIFY_TOKEN +uint16_t uniffi_livekit_uniffi_checksum_func_verify_token(void + +); +#endif +#ifndef UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_UNIFFI_CONTRACT_VERSION +#define UNIFFI_FFIDEF_FFI_LIVEKIT_UNIFFI_UNIFFI_CONTRACT_VERSION +uint32_t ffi_livekit_uniffi_uniffi_contract_version(void + +); +#endif + diff --git a/livekit-uniffi/generated/swift/livekit_uniffiFFI.modulemap b/livekit-uniffi/generated/swift/livekit_uniffiFFI.modulemap new file mode 100644 index 000000000..cce5c20c6 --- /dev/null +++ b/livekit-uniffi/generated/swift/livekit_uniffiFFI.modulemap @@ -0,0 +1,7 @@ +module livekit_uniffiFFI { + header "livekit_uniffiFFI.h" + export * + use "Darwin" + use "_Builtin_stdbool" + use "_Builtin_stdint" +} \ No newline at end of file diff --git a/livekit-uniffi/python_test/main.py b/livekit-uniffi/python_test/main.py new file mode 100644 index 000000000..1fc9e6d4a --- /dev/null +++ b/livekit-uniffi/python_test/main.py @@ -0,0 +1,41 @@ +import sys +import os + +sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..', 'generated', 'python'))) + +import asyncio +from livekit_uniffi import * + +def main(): + # Receive log messages from Rust + log_forward_bootstrap(level=LogForwardFilter.DEBUG) + + # Print FFI version + print(f"FFI version: v{build_version()}") + + credentials = ApiCredentials(key="devkey", secret="secret") + + jwt = generate_token( + options=TokenOptions(room_name="test", identity="some_participant"), + credentials=credentials, + ) + print(f"Generated JWT: {jwt}") + + decoded_grants = verify_token( + token=jwt, + credentials=credentials, + ) + print(f"Verified generated JWT: {decoded_grants}") + + async def receive_log_messages(): + while True: + message = await log_forward_receive() + if message is None: + print("Log forwarding ended") + break + print(f"Log from Rust: {message}") + + asyncio.run(receive_log_messages()) + +if __name__ == "__main__": + main() diff --git a/livekit-uniffi/src/access_token.rs b/livekit-uniffi/src/access_token.rs new file mode 100644 index 000000000..cbeb2af40 --- /dev/null +++ b/livekit-uniffi/src/access_token.rs @@ -0,0 +1,196 @@ +// Copyright 2025 LiveKit, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use livekit_api::access_token::{ + AccessToken, AccessTokenError, SIPGrants, TokenVerifier, VideoGrants, +}; +use std::{collections::HashMap, time::Duration}; + +/// An error that can occur during token generation or verification. +#[uniffi::remote(Error)] +#[uniffi(flat_error)] +pub enum AccessTokenError { + InvalidKeys, + InvalidEnv, + InvalidClaims, + Encoding, +} + +/// Room permissions +/// +/// Maps to the JWT's `video` field. +// +#[uniffi::remote(Record)] +pub struct VideoGrants { + pub room_create: bool, + pub room_list: bool, + pub room_record: bool, + pub room_admin: bool, + pub room_join: bool, + pub room: String, + pub destination_room: String, + pub can_publish: bool, + pub can_subscribe: bool, + pub can_publish_data: bool, + pub can_publish_sources: Vec, + pub can_update_own_metadata: bool, + pub ingress_admin: bool, + pub hidden: bool, + pub recorder: bool, +} + +/// SIP grants +/// +/// Maps to the JWT's `sip` field. +/// +#[uniffi::remote(Record)] +pub struct SIPGrants { + pub admin: bool, + pub call: bool, +} + +/// Claims decoded from a valid access token. +#[derive(uniffi::Record)] +pub struct Claims { + pub exp: u64, + pub iss: String, + pub nbf: u64, + pub sub: String, + pub name: String, + pub video: VideoGrants, + pub sip: SIPGrants, + pub sha256: String, + pub metadata: String, + pub attributes: HashMap, + + // Fields below have been flattened from the protocol-level `RoomConfiguration` message. + // Expose more fields as necessary for client use. + pub room_name: String, +} + +/// API credentials for access token generation and verification. +#[derive(uniffi::Record)] +pub struct ApiCredentials { + key: String, + secret: String, +} + +/// Options used for generating an access token. +/// +/// Any fields left empty will use the token generator's defaults. +/// +#[derive(uniffi::Record)] +pub struct TokenOptions { + #[uniffi(default)] + ttl: Option, + #[uniffi(default)] + video_grants: Option, + #[uniffi(default)] + sip_grants: Option, + #[uniffi(default)] + identity: Option, + #[uniffi(default)] + name: Option, + #[uniffi(default)] + metadata: Option, + #[uniffi(default)] + attributes: Option>, + #[uniffi(default)] + sha256: Option, + + // Fields below have been flattened from the protocol-level `RoomConfiguration` message. + // Expose more fields as necessary for client use. + #[uniffi(default)] + room_name: Option, +} + +/// Generates an access token. +/// +/// If `credentials` are omitted, API key and secret will be read from the environment +/// variables `LIVEKIT_API_KEY` and `LIVEKIT_SECRET` respectively. +/// +#[uniffi::export] +pub fn generate_token( + options: TokenOptions, + credentials: Option, +) -> Result { + // TODO: used to test log forwarding, remove + log::debug!("Generating access token"); + let mut token = match credentials { + Some(credentials) => AccessToken::with_api_key(&credentials.key, &credentials.secret), + None => AccessToken::new()?, + }; + if let Some(ttl) = options.ttl { + token = token.with_ttl(ttl); + } + if let Some(video_grants) = options.video_grants { + token = token.with_grants(video_grants); + } + if let Some(sip_grants) = options.sip_grants { + token = token.with_sip_grants(sip_grants); + } + if let Some(identity) = options.identity { + token = token.with_identity(&identity); + } + if let Some(name) = options.name { + token = token.with_name(&name); + } + if let Some(metadata) = options.metadata { + token = token.with_metadata(&metadata); + } + if let Some(attributes) = options.attributes { + token = token.with_attributes(&attributes); + } + if let Some(sha256) = options.sha256 { + token = token.with_sha256(&sha256); + } + let room_config = livekit_protocol::RoomConfiguration { + name: options.room_name.unwrap_or_default(), + ..Default::default() + }; + Ok(token.with_room_config(room_config).to_jwt()?) +} + +/// Verifies an access token. +/// +/// If `credentials` are omitted, API key and secret will be read from the environment +/// variables `LIVEKIT_API_KEY` and `LIVEKIT_SECRET` respectively. +/// +#[uniffi::export] +pub fn verify_token( + token: &str, + credentials: Option, +) -> Result { + // TODO: used to test log forwarding, remove + log::debug!("Verifying access token"); + let verifier = match credentials { + Some(credentials) => TokenVerifier::with_api_key(&credentials.key, &credentials.secret), + None => TokenVerifier::new()?, + }; + let claims = verifier.verify(token)?; + let room_name = claims.room_config.map_or(String::default(), |config| config.name); + Ok(Claims { + exp: claims.exp as u64, + iss: claims.iss, + nbf: claims.nbf as u64, + sub: claims.sub, + name: claims.name, + video: claims.video, + sip: claims.sip, + sha256: claims.sha256, + metadata: claims.metadata, + attributes: claims.attributes, + room_name, + }) +} diff --git a/livekit-uniffi/src/build_info.rs b/livekit-uniffi/src/build_info.rs new file mode 100644 index 000000000..54e521444 --- /dev/null +++ b/livekit-uniffi/src/build_info.rs @@ -0,0 +1,21 @@ +// Copyright 2025 LiveKit, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/// Returns the version specified in the crate's Cargo.toml. +#[uniffi::export] +pub fn build_version() -> String { + env!("CARGO_PKG_VERSION").to_string() +} + +// TODO: consider adding other info such as timestamp and Git hash. \ No newline at end of file diff --git a/livekit-uniffi/src/lib.rs b/livekit-uniffi/src/lib.rs new file mode 100644 index 000000000..15b5663c2 --- /dev/null +++ b/livekit-uniffi/src/lib.rs @@ -0,0 +1,26 @@ +// Copyright 2025 LiveKit, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/// Access token generation and verification from [`livekit-api::access_token`]. +pub mod access_token; + +/// Forward log messages from Rust. +pub mod log_forward; + +/// Information about the build such as version. +pub mod build_info; + +// TODO: expose more modules... + +uniffi::setup_scaffolding!(); diff --git a/livekit-uniffi/src/log_forward.rs b/livekit-uniffi/src/log_forward.rs new file mode 100644 index 000000000..58d4b4078 --- /dev/null +++ b/livekit-uniffi/src/log_forward.rs @@ -0,0 +1,105 @@ +// Copyright 2025 LiveKit, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use log::{Level, LevelFilter, Log, Record}; +use once_cell::sync::OnceCell; +use tokio::sync::{mpsc, Mutex}; + +/// Global logger instance. +static LOGGER: OnceCell = OnceCell::new(); + +/// Bootstraps log forwarding. +/// +/// Generally, you will invoke this once early in program execution. However, +/// subsequent invocations are allowed to change the log level. +/// +#[uniffi::export] +fn log_forward_bootstrap(level: LevelFilter) { + let logger = LOGGER.get_or_init(|| Logger::new()); + _ = log::set_logger(logger); // Returns an error if already set (ignore) + log::set_max_level(level); +} + +/// Asynchronously receives a forwarded log entry. +/// +/// Invoke repeatedly to receive log entries as they are produced +/// until `None` is returned, indicating forwarding has ended. Clients will +/// likely want to bridge this to the languages's equivalent of an asynchronous stream. +/// +#[uniffi::export] +async fn log_forward_receive() -> Option { + let logger = LOGGER.get().expect("Log forwarding not bootstrapped"); + logger.rx.try_lock().ok()?.recv().await +} + +#[uniffi::remote(Enum)] +#[uniffi(name = "LogForwardFilter")] +pub enum LevelFilter { + Off, + Error, + Warn, + Info, + Debug, + Trace, +} + +#[uniffi::remote(Enum)] +#[uniffi(name = "LogForwardLevel")] +pub enum Level { + Error, + Warn, + Info, + Debug, + Trace, +} + +#[derive(uniffi::Record)] +pub struct LogForwardEntry { + level: Level, + target: String, + file: Option, + line: Option, + message: String, +} +// TODO: can we expose static strings? + +struct Logger { + tx: mpsc::UnboundedSender, + rx: Mutex>, +} + +impl Logger { + fn new() -> Self { + let (tx, rx) = mpsc::unbounded_channel(); + Self { tx, rx: rx.into() } + } +} + +impl Log for Logger { + fn enabled(&self, _metadata: &log::Metadata) -> bool { + true + } + fn log(&self, record: &Record) { + let record = LogForwardEntry { + level: record.metadata().level(), + target: record.target().to_string(), + file: record.file().map(|s| s.to_string()), + line: record.line(), + message: record.args().to_string(), + }; + // TODO: expose module path and key-value pairs + self.tx.send(record).unwrap(); + } + fn flush(&self) {} +} diff --git a/livekit-uniffi/swift.sh b/livekit-uniffi/swift.sh new file mode 100755 index 000000000..1e86e31fa --- /dev/null +++ b/livekit-uniffi/swift.sh @@ -0,0 +1,82 @@ +#!/bin/bash +set -e + +UNIFFI_MODULE="livekit_uniffi" +LIB_NAME="lib${UNIFFI_MODULE}" +XCFRAMEWORK_NAME="LiveKitFFI" + +cargo build --release + +cargo run --bin uniffi-bindgen generate \ + --library "../target/release/${LIB_NAME}.dylib" \ + --language swift \ + --out-dir "generated/swift" + +# Required for xcframework +mv ./generated/swift/${UNIFFI_MODULE}FFI.modulemap ./generated/swift/module.modulemap + +RUSTUP_TARGETS=( + aarch64-apple-darwin + x86_64-apple-darwin + aarch64-apple-ios + aarch64-apple-ios-sim + x86_64-apple-ios + aarch64-apple-ios-macabi + x86_64-apple-ios-macabi +) + +TIER3_TARGETS=( + aarch64-apple-tvos + aarch64-apple-visionos + aarch64-apple-tvos-sim + aarch64-apple-visionos-sim +) + +for target in "${RUSTUP_TARGETS[@]}"; do + rustup target add "$target" +done + +for target in "${RUSTUP_TARGETS[@]}"; do + cargo build --release --target "$target" +done + +for target in "${TIER3_TARGETS[@]}"; do + cargo +nightly build -Zbuild-std=std,panic_abort --release --target="$target" +done + +UNIVERSAL_BINARIES=( + "ios-simulator:aarch64-apple-ios-sim:x86_64-apple-ios" + "macos:aarch64-apple-darwin:x86_64-apple-darwin" + "ios-macabi:aarch64-apple-ios-macabi:x86_64-apple-ios-macabi" +) + +for config in "${UNIVERSAL_BINARIES[@]}"; do + IFS=':' read -r output_dir arch1 arch2 <<< "$config" + mkdir -p "../target/${output_dir}/release" + lipo -create \ + "../target/${arch1}/release/${LIB_NAME}.a" \ + "../target/${arch2}/release/${LIB_NAME}.a" \ + -output "../target/${output_dir}/release/${LIB_NAME}.a" +done + +rm -rf "../target/${XCFRAMEWORK_NAME}.xcframework" + +XCFRAMEWORK_LIBS=( + "../target/aarch64-apple-ios/release/${LIB_NAME}.a" + "../target/ios-simulator/release/${LIB_NAME}.a" + "../target/macos/release/${LIB_NAME}.a" + "../target/ios-macabi/release/${LIB_NAME}.a" + "../target/aarch64-apple-tvos/release/${LIB_NAME}.a" + "../target/aarch64-apple-visionos/release/${LIB_NAME}.a" + "../target/aarch64-apple-tvos-sim/release/${LIB_NAME}.a" + "../target/aarch64-apple-visionos-sim/release/${LIB_NAME}.a" +) + +XCFRAMEWORK_ARGS=() +for lib in "${XCFRAMEWORK_LIBS[@]}"; do + XCFRAMEWORK_ARGS+=(-library "$lib" -headers ./generated/swift) +done + +xcodebuild -create-xcframework \ + "${XCFRAMEWORK_ARGS[@]}" \ + -output "../target/${XCFRAMEWORK_NAME}.xcframework" diff --git a/livekit-uniffi/uniffi.toml b/livekit-uniffi/uniffi.toml new file mode 100644 index 000000000..6ab94cf93 --- /dev/null +++ b/livekit-uniffi/uniffi.toml @@ -0,0 +1 @@ +# Configuration file for UniFFI binding generation; add options here as needed. \ No newline at end of file