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/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..afcff8988
--- /dev/null
+++ b/livekit-uniffi/bindgen.sh
@@ -0,0 +1,21 @@
+#!/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
+
+
+cargo install uniffi-bindgen-cs --git https://github.com/NordSecurity/uniffi-bindgen-cs --tag v0.10.0+v0.29.4
+uniffi-bindgen-cs --library ../target/release/liblivekit_uniffi.dylib --out-dir generated/csharp
\ No newline at end of file
diff --git a/livekit-uniffi/generated/csharp/livekit_uniffi.cs b/livekit-uniffi/generated/csharp/livekit_uniffi.cs
new file mode 100644
index 000000000..9335b3480
--- /dev/null
+++ b/livekit-uniffi/generated/csharp/livekit_uniffi.cs
@@ -0,0 +1,2666 @@
+//
+// This file was generated by uniffi-bindgen-cs v0.10.0+v0.29.4
+// See https://github.com/NordSecurity/uniffi-bindgen-cs for more information.
+//
+
+#nullable enable
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace uniffi.livekit_uniffi;
+
+// 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.
+
+[StructLayout(LayoutKind.Sequential)]
+internal struct RustBuffer
+{
+ public ulong capacity;
+ public ulong len;
+ public IntPtr data;
+
+ public static RustBuffer Alloc(int size)
+ {
+ return _UniffiHelpers.RustCall(
+ (ref UniffiRustCallStatus status) =>
+ {
+ var buffer = _UniFFILib.ffi_livekit_uniffi_rustbuffer_alloc(
+ Convert.ToUInt64(size),
+ ref status
+ );
+ if (buffer.data == IntPtr.Zero)
+ {
+ throw new AllocationException(
+ $"RustBuffer.Alloc() returned null data pointer (size={size})"
+ );
+ }
+ return buffer;
+ }
+ );
+ }
+
+ public static void Free(RustBuffer buffer)
+ {
+ _UniffiHelpers.RustCall(
+ (ref UniffiRustCallStatus status) =>
+ {
+ _UniFFILib.ffi_livekit_uniffi_rustbuffer_free(buffer, ref status);
+ }
+ );
+ }
+
+ public static BigEndianStream MemoryStream(IntPtr data, long length)
+ {
+ unsafe
+ {
+ return new BigEndianStream(new UnmanagedMemoryStream((byte*)data.ToPointer(), length));
+ }
+ }
+
+ public BigEndianStream AsStream()
+ {
+ unsafe
+ {
+ return new BigEndianStream(
+ new UnmanagedMemoryStream((byte*)data.ToPointer(), Convert.ToInt64(len))
+ );
+ }
+ }
+
+ public BigEndianStream AsWriteableStream()
+ {
+ unsafe
+ {
+ return new BigEndianStream(
+ new UnmanagedMemoryStream(
+ (byte*)data.ToPointer(),
+ Convert.ToInt64(capacity),
+ Convert.ToInt64(capacity),
+ FileAccess.Write
+ )
+ );
+ }
+ }
+}
+
+// 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 managed memory, 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.
+
+[StructLayout(LayoutKind.Sequential)]
+internal struct ForeignBytes
+{
+ public int length;
+ public IntPtr data;
+}
+
+// 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.
+internal abstract class FfiConverter
+{
+ // Convert an FFI type to a C# type
+ public abstract CsType Lift(FfiType value);
+
+ // Convert C# type to an FFI type
+ public abstract FfiType Lower(CsType value);
+
+ // Read a C# type from a `ByteBuffer`
+ public abstract CsType Read(BigEndianStream stream);
+
+ // 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.
+ public abstract int AllocationSize(CsType value);
+
+ // Write a C# type to a `ByteBuffer`
+ public abstract void Write(CsType value, BigEndianStream stream);
+
+ // 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.
+ public RustBuffer LowerIntoRustBuffer(CsType value)
+ {
+ var rbuf = RustBuffer.Alloc(AllocationSize(value));
+ try
+ {
+ var stream = rbuf.AsWriteableStream();
+ Write(value, stream);
+ rbuf.len = Convert.ToUInt64(stream.Position);
+ return rbuf;
+ }
+ catch
+ {
+ RustBuffer.Free(rbuf);
+ throw;
+ }
+ }
+
+ // 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.
+ protected CsType LiftFromRustBuffer(RustBuffer rbuf)
+ {
+ var stream = rbuf.AsStream();
+ try
+ {
+ var item = Read(stream);
+ if (stream.HasRemaining())
+ {
+ throw new InternalException(
+ "junk remaining in buffer after lifting, something is very wrong!!"
+ );
+ }
+ return item;
+ }
+ finally
+ {
+ RustBuffer.Free(rbuf);
+ }
+ }
+}
+
+// FfiConverter that uses `RustBuffer` as the FfiType
+internal abstract class FfiConverterRustBuffer : FfiConverter
+{
+ public override CsType Lift(RustBuffer value)
+ {
+ return LiftFromRustBuffer(value);
+ }
+
+ public override RustBuffer Lower(CsType value)
+ {
+ return LowerIntoRustBuffer(value);
+ }
+}
+
+// A handful of classes and functions to support the generated data structures.
+// This would be a good candidate for isolating in its own ffi-support lib.
+// Error runtime.
+[StructLayout(LayoutKind.Sequential)]
+struct UniffiRustCallStatus
+{
+ public sbyte code;
+ public RustBuffer error_buf;
+
+ public bool IsSuccess()
+ {
+ return code == 0;
+ }
+
+ public bool IsError()
+ {
+ return code == 1;
+ }
+
+ public bool IsPanic()
+ {
+ return code == 2;
+ }
+}
+
+// Base class for all uniffi exceptions
+internal class UniffiException : System.Exception
+{
+ public UniffiException()
+ : base() { }
+
+ public UniffiException(string message)
+ : base(message) { }
+}
+
+internal class UndeclaredErrorException : UniffiException
+{
+ public UndeclaredErrorException(string message)
+ : base(message) { }
+}
+
+internal class PanicException : UniffiException
+{
+ public PanicException(string message)
+ : base(message) { }
+}
+
+internal class AllocationException : UniffiException
+{
+ public AllocationException(string message)
+ : base(message) { }
+}
+
+internal class InternalException : UniffiException
+{
+ public InternalException(string message)
+ : base(message) { }
+}
+
+internal class InvalidEnumException : InternalException
+{
+ public InvalidEnumException(string message)
+ : base(message) { }
+}
+
+internal class UniffiContractVersionException : UniffiException
+{
+ public UniffiContractVersionException(string message)
+ : base(message) { }
+}
+
+internal class UniffiContractChecksumException : UniffiException
+{
+ public UniffiContractChecksumException(string message)
+ : base(message) { }
+}
+
+// Each top-level error class has a companion object that can lift the error from the call status's rust buffer
+interface CallStatusErrorHandler
+ where E : System.Exception
+{
+ E Lift(RustBuffer error_buf);
+}
+
+// CallStatusErrorHandler implementation for times when we don't expect a CALL_ERROR
+class NullCallStatusErrorHandler : CallStatusErrorHandler
+{
+ public static NullCallStatusErrorHandler INSTANCE = new NullCallStatusErrorHandler();
+
+ public UniffiException Lift(RustBuffer error_buf)
+ {
+ RustBuffer.Free(error_buf);
+ return new UndeclaredErrorException(
+ "library has returned an error not declared in UNIFFI interface file"
+ );
+ }
+}
+
+// Helpers for calling Rust
+// In practice we usually need to be synchronized to call this safely, so it doesn't
+// synchronize itself
+class _UniffiHelpers
+{
+ public delegate void RustCallAction(ref UniffiRustCallStatus status);
+ public delegate U RustCallFunc(ref UniffiRustCallStatus status);
+
+ // Call a rust function that returns a Result<>. Pass in the Error class companion that corresponds to the Err
+ public static U RustCallWithError(
+ CallStatusErrorHandler errorHandler,
+ RustCallFunc callback
+ )
+ where E : UniffiException
+ {
+ var status = new UniffiRustCallStatus();
+ var return_value = callback(ref status);
+ if (status.IsSuccess())
+ {
+ return return_value;
+ }
+ 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 new PanicException(FfiConverterString.INSTANCE.Lift(status.error_buf));
+ }
+ else
+ {
+ throw new PanicException("Rust panic");
+ }
+ }
+ else
+ {
+ throw new InternalException($"Unknown rust call status: {status.code}");
+ }
+ }
+
+ // Call a rust function that returns a Result<>. Pass in the Error class companion that corresponds to the Err
+ public static void RustCallWithError(
+ CallStatusErrorHandler errorHandler,
+ RustCallAction callback
+ )
+ where E : UniffiException
+ {
+ _UniffiHelpers.RustCallWithError(
+ errorHandler,
+ (ref UniffiRustCallStatus status) =>
+ {
+ callback(ref status);
+ return 0;
+ }
+ );
+ }
+
+ // Call a rust function that returns a plain value
+ public static U RustCall(RustCallFunc callback)
+ {
+ return _UniffiHelpers.RustCallWithError(NullCallStatusErrorHandler.INSTANCE, callback);
+ }
+
+ // Call a rust function that returns a plain value
+ public static void RustCall(RustCallAction callback)
+ {
+ _UniffiHelpers.RustCall(
+ (ref UniffiRustCallStatus status) =>
+ {
+ callback(ref status);
+ return 0;
+ }
+ );
+ }
+}
+
+static class FFIObjectUtil
+{
+ public static void DisposeAll(params Object?[] list)
+ {
+ Dispose(list);
+ }
+
+ // Dispose is implemented by recursive type inspection at runtime. This is because
+ // generating correct Dispose calls for recursive complex types, e.g. List>
+ // is quite cumbersome.
+ private static void Dispose(Object? obj)
+ {
+ if (obj == null)
+ {
+ return;
+ }
+
+ if (obj is IDisposable disposable)
+ {
+ disposable.Dispose();
+ return;
+ }
+
+ var objType = obj.GetType();
+ var typeCode = Type.GetTypeCode(objType);
+ if (typeCode != TypeCode.Object)
+ {
+ return;
+ }
+
+ var genericArguments = objType.GetGenericArguments();
+ if (genericArguments.Length == 0 && !objType.IsArray)
+ {
+ return;
+ }
+
+ if (obj is System.Collections.IDictionary objDictionary)
+ {
+ //This extra code tests to not call "Dispose" for a Dictionary()
+ //for all values as "double" and alike doesn't support interface "IDisposable"
+ var valuesType = objType.GetGenericArguments()[1];
+ var elementValuesTypeCode = Type.GetTypeCode(valuesType);
+ if (elementValuesTypeCode != TypeCode.Object)
+ {
+ return;
+ }
+ foreach (var value in objDictionary.Values)
+ {
+ Dispose(value);
+ }
+ }
+ else if (obj is System.Collections.IEnumerable listValues)
+ {
+ //This extra code tests to not call "Dispose" for a List()
+ //for all keys as "int" and alike doesn't support interface "IDisposable"
+ var elementType = objType.IsArray ? objType.GetElementType() : genericArguments[0];
+ var elementValuesTypeCode = Type.GetTypeCode(elementType);
+ if (elementValuesTypeCode != TypeCode.Object)
+ {
+ return;
+ }
+ foreach (var value in listValues)
+ {
+ Dispose(value);
+ }
+ }
+ }
+}
+
+// Big endian streams are not yet available in dotnet :'(
+// https://github.com/dotnet/runtime/issues/26904
+
+class StreamUnderflowException : System.Exception
+{
+ public StreamUnderflowException() { }
+}
+
+static class BigEndianStreamExtensions
+{
+ public static void WriteInt32(this Stream stream, int value, int bytesToWrite = 4)
+ {
+#if DOTNET_8_0_OR_GREATER
+ Span buffer = stackalloc byte[bytesToWrite];
+#else
+ byte[] buffer = new byte[bytesToWrite];
+#endif
+ var posByte = bytesToWrite;
+ while (posByte != 0)
+ {
+ posByte--;
+ buffer[posByte] = (byte)(value);
+ value >>= 8;
+ }
+
+#if DOTNET_8_0_OR_GREATER
+ stream.Write(buffer);
+#else
+ stream.Write(buffer, 0, buffer.Length);
+#endif
+ }
+
+ public static void WriteInt64(this Stream stream, long value)
+ {
+ int bytesToWrite = 8;
+#if DOTNET_8_0_OR_GREATER
+ Span buffer = stackalloc byte[bytesToWrite];
+#else
+ byte[] buffer = new byte[bytesToWrite];
+#endif
+ var posByte = bytesToWrite;
+ while (posByte != 0)
+ {
+ posByte--;
+ buffer[posByte] = (byte)(value);
+ value >>= 8;
+ }
+
+#if DOTNET_8_0_OR_GREATER
+ stream.Write(buffer);
+#else
+ stream.Write(buffer, 0, buffer.Length);
+#endif
+ }
+
+ public static uint ReadUint32(this Stream stream, int bytesToRead = 4)
+ {
+ CheckRemaining(stream, bytesToRead);
+#if DOTNET_8_0_OR_GREATER
+ Span buffer = stackalloc byte[bytesToRead];
+ stream.Read(buffer);
+#else
+ byte[] buffer = new byte[bytesToRead];
+ stream.Read(buffer, 0, bytesToRead);
+#endif
+ uint result = 0;
+ uint digitMultiplier = 1;
+ int posByte = bytesToRead;
+ while (posByte != 0)
+ {
+ posByte--;
+ result |= buffer[posByte] * digitMultiplier;
+ digitMultiplier <<= 8;
+ }
+
+ return result;
+ }
+
+ public static ulong ReadUInt64(this Stream stream)
+ {
+ int bytesToRead = 8;
+ CheckRemaining(stream, bytesToRead);
+#if DOTNET_8_0_OR_GREATER
+ Span buffer = stackalloc byte[bytesToRead];
+ stream.Read(buffer);
+#else
+ byte[] buffer = new byte[bytesToRead];
+ stream.Read(buffer, 0, bytesToRead);
+#endif
+ ulong result = 0;
+ ulong digitMultiplier = 1;
+ int posByte = bytesToRead;
+ while (posByte != 0)
+ {
+ posByte--;
+ result |= buffer[posByte] * digitMultiplier;
+ digitMultiplier <<= 8;
+ }
+
+ return result;
+ }
+
+ public static void CheckRemaining(this Stream stream, int length)
+ {
+ if (stream.Length - stream.Position < length)
+ {
+ throw new StreamUnderflowException();
+ }
+ }
+
+ public static void ForEach(this T[] items, Action action)
+ {
+ foreach (var item in items)
+ {
+ action(item);
+ }
+ }
+}
+
+class BigEndianStream
+{
+ Stream stream;
+
+ public BigEndianStream(Stream stream)
+ {
+ this.stream = stream;
+ }
+
+ public bool HasRemaining()
+ {
+ return (stream.Length - Position) > 0;
+ }
+
+ public long Position
+ {
+ get => stream.Position;
+ set => stream.Position = value;
+ }
+
+ public void WriteBytes(byte[] buffer)
+ {
+#if DOTNET_8_0_OR_GREATER
+ stream.Write(buffer);
+#else
+ stream.Write(buffer, 0, buffer.Length);
+#endif
+ }
+
+ public void WriteByte(byte value) => stream.WriteInt32(value, bytesToWrite: 1);
+
+ public void WriteSByte(sbyte value) => stream.WriteInt32(value, bytesToWrite: 1);
+
+ public void WriteUShort(ushort value) => stream.WriteInt32(value, bytesToWrite: 2);
+
+ public void WriteShort(short value) => stream.WriteInt32(value, bytesToWrite: 2);
+
+ public void WriteUInt(uint value) => stream.WriteInt32((int)value);
+
+ public void WriteInt(int value) => stream.WriteInt32(value);
+
+ public void WriteULong(ulong value) => stream.WriteInt64((long)value);
+
+ public void WriteLong(long value) => stream.WriteInt64(value);
+
+ public void WriteFloat(float value)
+ {
+ unsafe
+ {
+ WriteInt(*((int*)&value));
+ }
+ }
+
+ public void WriteDouble(double value) =>
+ stream.WriteInt64(BitConverter.DoubleToInt64Bits(value));
+
+ public byte[] ReadBytes(int length)
+ {
+ stream.CheckRemaining(length);
+ byte[] result = new byte[length];
+ stream.Read(result, 0, length);
+ return result;
+ }
+
+ public byte ReadByte() => (byte)stream.ReadUint32(bytesToRead: 1);
+
+ public ushort ReadUShort() => (ushort)stream.ReadUint32(bytesToRead: 2);
+
+ public uint ReadUInt() => (uint)stream.ReadUint32(bytesToRead: 4);
+
+ public ulong ReadULong() => stream.ReadUInt64();
+
+ public sbyte ReadSByte() => (sbyte)ReadByte();
+
+ public short ReadShort() => (short)ReadUShort();
+
+ public int ReadInt() => (int)ReadUInt();
+
+ public float ReadFloat()
+ {
+ unsafe
+ {
+ int value = ReadInt();
+ return *((float*)&value);
+ }
+ }
+
+ public long ReadLong() => (long)ReadULong();
+
+ public double ReadDouble() => BitConverter.Int64BitsToDouble(ReadLong());
+}
+
+// Contains loading, initialization code,
+// and the FFI Function declarations in a com.sun.jna.Library.
+
+// This is an implementation detail that will be called internally by the public API.
+static class _UniFFILib
+{
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ public delegate void UniffiRustFutureContinuationCallback(ulong @data, sbyte @pollResult);
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ public delegate void UniffiForeignFutureFree(ulong @handle);
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ public delegate void UniffiCallbackInterfaceFree(ulong @handle);
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct UniffiForeignFuture
+ {
+ public ulong @handle;
+ public IntPtr @free;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct UniffiForeignFutureStructU8
+ {
+ public byte @returnValue;
+ public UniffiRustCallStatus @callStatus;
+ }
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ public delegate void UniffiForeignFutureCompleteU8(
+ ulong @callbackData,
+ _UniFFILib.UniffiForeignFutureStructU8 @result
+ );
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct UniffiForeignFutureStructI8
+ {
+ public sbyte @returnValue;
+ public UniffiRustCallStatus @callStatus;
+ }
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ public delegate void UniffiForeignFutureCompleteI8(
+ ulong @callbackData,
+ _UniFFILib.UniffiForeignFutureStructI8 @result
+ );
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct UniffiForeignFutureStructU16
+ {
+ public ushort @returnValue;
+ public UniffiRustCallStatus @callStatus;
+ }
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ public delegate void UniffiForeignFutureCompleteU16(
+ ulong @callbackData,
+ _UniFFILib.UniffiForeignFutureStructU16 @result
+ );
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct UniffiForeignFutureStructI16
+ {
+ public short @returnValue;
+ public UniffiRustCallStatus @callStatus;
+ }
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ public delegate void UniffiForeignFutureCompleteI16(
+ ulong @callbackData,
+ _UniFFILib.UniffiForeignFutureStructI16 @result
+ );
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct UniffiForeignFutureStructU32
+ {
+ public uint @returnValue;
+ public UniffiRustCallStatus @callStatus;
+ }
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ public delegate void UniffiForeignFutureCompleteU32(
+ ulong @callbackData,
+ _UniFFILib.UniffiForeignFutureStructU32 @result
+ );
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct UniffiForeignFutureStructI32
+ {
+ public int @returnValue;
+ public UniffiRustCallStatus @callStatus;
+ }
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ public delegate void UniffiForeignFutureCompleteI32(
+ ulong @callbackData,
+ _UniFFILib.UniffiForeignFutureStructI32 @result
+ );
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct UniffiForeignFutureStructU64
+ {
+ public ulong @returnValue;
+ public UniffiRustCallStatus @callStatus;
+ }
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ public delegate void UniffiForeignFutureCompleteU64(
+ ulong @callbackData,
+ _UniFFILib.UniffiForeignFutureStructU64 @result
+ );
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct UniffiForeignFutureStructI64
+ {
+ public long @returnValue;
+ public UniffiRustCallStatus @callStatus;
+ }
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ public delegate void UniffiForeignFutureCompleteI64(
+ ulong @callbackData,
+ _UniFFILib.UniffiForeignFutureStructI64 @result
+ );
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct UniffiForeignFutureStructF32
+ {
+ public float @returnValue;
+ public UniffiRustCallStatus @callStatus;
+ }
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ public delegate void UniffiForeignFutureCompleteF32(
+ ulong @callbackData,
+ _UniFFILib.UniffiForeignFutureStructF32 @result
+ );
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct UniffiForeignFutureStructF64
+ {
+ public double @returnValue;
+ public UniffiRustCallStatus @callStatus;
+ }
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ public delegate void UniffiForeignFutureCompleteF64(
+ ulong @callbackData,
+ _UniFFILib.UniffiForeignFutureStructF64 @result
+ );
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct UniffiForeignFutureStructPointer
+ {
+ public IntPtr @returnValue;
+ public UniffiRustCallStatus @callStatus;
+ }
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ public delegate void UniffiForeignFutureCompletePointer(
+ ulong @callbackData,
+ _UniFFILib.UniffiForeignFutureStructPointer @result
+ );
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct UniffiForeignFutureStructRustBuffer
+ {
+ public RustBuffer @returnValue;
+ public UniffiRustCallStatus @callStatus;
+ }
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ public delegate void UniffiForeignFutureCompleteRustBuffer(
+ ulong @callbackData,
+ _UniFFILib.UniffiForeignFutureStructRustBuffer @result
+ );
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct UniffiForeignFutureStructVoid
+ {
+ public UniffiRustCallStatus @callStatus;
+ }
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ public delegate void UniffiForeignFutureCompleteVoid(
+ ulong @callbackData,
+ _UniFFILib.UniffiForeignFutureStructVoid @result
+ );
+
+ static _UniFFILib()
+ {
+ _UniFFILib.uniffiCheckContractApiVersion();
+ _UniFFILib.uniffiCheckApiChecksums();
+ }
+
+ [DllImport("livekit_uniffi", CallingConvention = CallingConvention.Cdecl)]
+ public static extern RustBuffer uniffi_livekit_uniffi_fn_func_build_version(
+ ref UniffiRustCallStatus _uniffi_out_err
+ );
+
+ [DllImport("livekit_uniffi", CallingConvention = CallingConvention.Cdecl)]
+ public static extern RustBuffer uniffi_livekit_uniffi_fn_func_generate_token(
+ RustBuffer @options,
+ RustBuffer @credentials,
+ ref UniffiRustCallStatus _uniffi_out_err
+ );
+
+ [DllImport("livekit_uniffi", CallingConvention = CallingConvention.Cdecl)]
+ public static extern void uniffi_livekit_uniffi_fn_func_log_forward_bootstrap(
+ RustBuffer @level,
+ ref UniffiRustCallStatus _uniffi_out_err
+ );
+
+ [DllImport("livekit_uniffi", CallingConvention = CallingConvention.Cdecl)]
+ public static extern IntPtr uniffi_livekit_uniffi_fn_func_log_forward_receive();
+
+ [DllImport("livekit_uniffi", CallingConvention = CallingConvention.Cdecl)]
+ public static extern RustBuffer uniffi_livekit_uniffi_fn_func_verify_token(
+ RustBuffer @token,
+ RustBuffer @credentials,
+ ref UniffiRustCallStatus _uniffi_out_err
+ );
+
+ [DllImport("livekit_uniffi", CallingConvention = CallingConvention.Cdecl)]
+ public static extern RustBuffer ffi_livekit_uniffi_rustbuffer_alloc(
+ ulong @size,
+ ref UniffiRustCallStatus _uniffi_out_err
+ );
+
+ [DllImport("livekit_uniffi", CallingConvention = CallingConvention.Cdecl)]
+ public static extern RustBuffer ffi_livekit_uniffi_rustbuffer_from_bytes(
+ ForeignBytes @bytes,
+ ref UniffiRustCallStatus _uniffi_out_err
+ );
+
+ [DllImport("livekit_uniffi", CallingConvention = CallingConvention.Cdecl)]
+ public static extern void ffi_livekit_uniffi_rustbuffer_free(
+ RustBuffer @buf,
+ ref UniffiRustCallStatus _uniffi_out_err
+ );
+
+ [DllImport("livekit_uniffi", CallingConvention = CallingConvention.Cdecl)]
+ public static extern RustBuffer ffi_livekit_uniffi_rustbuffer_reserve(
+ RustBuffer @buf,
+ ulong @additional,
+ ref UniffiRustCallStatus _uniffi_out_err
+ );
+
+ [DllImport("livekit_uniffi", CallingConvention = CallingConvention.Cdecl)]
+ public static extern void ffi_livekit_uniffi_rust_future_poll_u8(
+ IntPtr @handle,
+ IntPtr @callback,
+ IntPtr @callbackData
+ );
+
+ [DllImport("livekit_uniffi", CallingConvention = CallingConvention.Cdecl)]
+ public static extern void ffi_livekit_uniffi_rust_future_cancel_u8(IntPtr @handle);
+
+ [DllImport("livekit_uniffi", CallingConvention = CallingConvention.Cdecl)]
+ public static extern void ffi_livekit_uniffi_rust_future_free_u8(IntPtr @handle);
+
+ [DllImport("livekit_uniffi", CallingConvention = CallingConvention.Cdecl)]
+ public static extern byte ffi_livekit_uniffi_rust_future_complete_u8(
+ IntPtr @handle,
+ ref UniffiRustCallStatus _uniffi_out_err
+ );
+
+ [DllImport("livekit_uniffi", CallingConvention = CallingConvention.Cdecl)]
+ public static extern void ffi_livekit_uniffi_rust_future_poll_i8(
+ IntPtr @handle,
+ IntPtr @callback,
+ IntPtr @callbackData
+ );
+
+ [DllImport("livekit_uniffi", CallingConvention = CallingConvention.Cdecl)]
+ public static extern void ffi_livekit_uniffi_rust_future_cancel_i8(IntPtr @handle);
+
+ [DllImport("livekit_uniffi", CallingConvention = CallingConvention.Cdecl)]
+ public static extern void ffi_livekit_uniffi_rust_future_free_i8(IntPtr @handle);
+
+ [DllImport("livekit_uniffi", CallingConvention = CallingConvention.Cdecl)]
+ public static extern sbyte ffi_livekit_uniffi_rust_future_complete_i8(
+ IntPtr @handle,
+ ref UniffiRustCallStatus _uniffi_out_err
+ );
+
+ [DllImport("livekit_uniffi", CallingConvention = CallingConvention.Cdecl)]
+ public static extern void ffi_livekit_uniffi_rust_future_poll_u16(
+ IntPtr @handle,
+ IntPtr @callback,
+ IntPtr @callbackData
+ );
+
+ [DllImport("livekit_uniffi", CallingConvention = CallingConvention.Cdecl)]
+ public static extern void ffi_livekit_uniffi_rust_future_cancel_u16(IntPtr @handle);
+
+ [DllImport("livekit_uniffi", CallingConvention = CallingConvention.Cdecl)]
+ public static extern void ffi_livekit_uniffi_rust_future_free_u16(IntPtr @handle);
+
+ [DllImport("livekit_uniffi", CallingConvention = CallingConvention.Cdecl)]
+ public static extern ushort ffi_livekit_uniffi_rust_future_complete_u16(
+ IntPtr @handle,
+ ref UniffiRustCallStatus _uniffi_out_err
+ );
+
+ [DllImport("livekit_uniffi", CallingConvention = CallingConvention.Cdecl)]
+ public static extern void ffi_livekit_uniffi_rust_future_poll_i16(
+ IntPtr @handle,
+ IntPtr @callback,
+ IntPtr @callbackData
+ );
+
+ [DllImport("livekit_uniffi", CallingConvention = CallingConvention.Cdecl)]
+ public static extern void ffi_livekit_uniffi_rust_future_cancel_i16(IntPtr @handle);
+
+ [DllImport("livekit_uniffi", CallingConvention = CallingConvention.Cdecl)]
+ public static extern void ffi_livekit_uniffi_rust_future_free_i16(IntPtr @handle);
+
+ [DllImport("livekit_uniffi", CallingConvention = CallingConvention.Cdecl)]
+ public static extern short ffi_livekit_uniffi_rust_future_complete_i16(
+ IntPtr @handle,
+ ref UniffiRustCallStatus _uniffi_out_err
+ );
+
+ [DllImport("livekit_uniffi", CallingConvention = CallingConvention.Cdecl)]
+ public static extern void ffi_livekit_uniffi_rust_future_poll_u32(
+ IntPtr @handle,
+ IntPtr @callback,
+ IntPtr @callbackData
+ );
+
+ [DllImport("livekit_uniffi", CallingConvention = CallingConvention.Cdecl)]
+ public static extern void ffi_livekit_uniffi_rust_future_cancel_u32(IntPtr @handle);
+
+ [DllImport("livekit_uniffi", CallingConvention = CallingConvention.Cdecl)]
+ public static extern void ffi_livekit_uniffi_rust_future_free_u32(IntPtr @handle);
+
+ [DllImport("livekit_uniffi", CallingConvention = CallingConvention.Cdecl)]
+ public static extern uint ffi_livekit_uniffi_rust_future_complete_u32(
+ IntPtr @handle,
+ ref UniffiRustCallStatus _uniffi_out_err
+ );
+
+ [DllImport("livekit_uniffi", CallingConvention = CallingConvention.Cdecl)]
+ public static extern void ffi_livekit_uniffi_rust_future_poll_i32(
+ IntPtr @handle,
+ IntPtr @callback,
+ IntPtr @callbackData
+ );
+
+ [DllImport("livekit_uniffi", CallingConvention = CallingConvention.Cdecl)]
+ public static extern void ffi_livekit_uniffi_rust_future_cancel_i32(IntPtr @handle);
+
+ [DllImport("livekit_uniffi", CallingConvention = CallingConvention.Cdecl)]
+ public static extern void ffi_livekit_uniffi_rust_future_free_i32(IntPtr @handle);
+
+ [DllImport("livekit_uniffi", CallingConvention = CallingConvention.Cdecl)]
+ public static extern int ffi_livekit_uniffi_rust_future_complete_i32(
+ IntPtr @handle,
+ ref UniffiRustCallStatus _uniffi_out_err
+ );
+
+ [DllImport("livekit_uniffi", CallingConvention = CallingConvention.Cdecl)]
+ public static extern void ffi_livekit_uniffi_rust_future_poll_u64(
+ IntPtr @handle,
+ IntPtr @callback,
+ IntPtr @callbackData
+ );
+
+ [DllImport("livekit_uniffi", CallingConvention = CallingConvention.Cdecl)]
+ public static extern void ffi_livekit_uniffi_rust_future_cancel_u64(IntPtr @handle);
+
+ [DllImport("livekit_uniffi", CallingConvention = CallingConvention.Cdecl)]
+ public static extern void ffi_livekit_uniffi_rust_future_free_u64(IntPtr @handle);
+
+ [DllImport("livekit_uniffi", CallingConvention = CallingConvention.Cdecl)]
+ public static extern ulong ffi_livekit_uniffi_rust_future_complete_u64(
+ IntPtr @handle,
+ ref UniffiRustCallStatus _uniffi_out_err
+ );
+
+ [DllImport("livekit_uniffi", CallingConvention = CallingConvention.Cdecl)]
+ public static extern void ffi_livekit_uniffi_rust_future_poll_i64(
+ IntPtr @handle,
+ IntPtr @callback,
+ IntPtr @callbackData
+ );
+
+ [DllImport("livekit_uniffi", CallingConvention = CallingConvention.Cdecl)]
+ public static extern void ffi_livekit_uniffi_rust_future_cancel_i64(IntPtr @handle);
+
+ [DllImport("livekit_uniffi", CallingConvention = CallingConvention.Cdecl)]
+ public static extern void ffi_livekit_uniffi_rust_future_free_i64(IntPtr @handle);
+
+ [DllImport("livekit_uniffi", CallingConvention = CallingConvention.Cdecl)]
+ public static extern long ffi_livekit_uniffi_rust_future_complete_i64(
+ IntPtr @handle,
+ ref UniffiRustCallStatus _uniffi_out_err
+ );
+
+ [DllImport("livekit_uniffi", CallingConvention = CallingConvention.Cdecl)]
+ public static extern void ffi_livekit_uniffi_rust_future_poll_f32(
+ IntPtr @handle,
+ IntPtr @callback,
+ IntPtr @callbackData
+ );
+
+ [DllImport("livekit_uniffi", CallingConvention = CallingConvention.Cdecl)]
+ public static extern void ffi_livekit_uniffi_rust_future_cancel_f32(IntPtr @handle);
+
+ [DllImport("livekit_uniffi", CallingConvention = CallingConvention.Cdecl)]
+ public static extern void ffi_livekit_uniffi_rust_future_free_f32(IntPtr @handle);
+
+ [DllImport("livekit_uniffi", CallingConvention = CallingConvention.Cdecl)]
+ public static extern float ffi_livekit_uniffi_rust_future_complete_f32(
+ IntPtr @handle,
+ ref UniffiRustCallStatus _uniffi_out_err
+ );
+
+ [DllImport("livekit_uniffi", CallingConvention = CallingConvention.Cdecl)]
+ public static extern void ffi_livekit_uniffi_rust_future_poll_f64(
+ IntPtr @handle,
+ IntPtr @callback,
+ IntPtr @callbackData
+ );
+
+ [DllImport("livekit_uniffi", CallingConvention = CallingConvention.Cdecl)]
+ public static extern void ffi_livekit_uniffi_rust_future_cancel_f64(IntPtr @handle);
+
+ [DllImport("livekit_uniffi", CallingConvention = CallingConvention.Cdecl)]
+ public static extern void ffi_livekit_uniffi_rust_future_free_f64(IntPtr @handle);
+
+ [DllImport("livekit_uniffi", CallingConvention = CallingConvention.Cdecl)]
+ public static extern double ffi_livekit_uniffi_rust_future_complete_f64(
+ IntPtr @handle,
+ ref UniffiRustCallStatus _uniffi_out_err
+ );
+
+ [DllImport("livekit_uniffi", CallingConvention = CallingConvention.Cdecl)]
+ public static extern void ffi_livekit_uniffi_rust_future_poll_pointer(
+ IntPtr @handle,
+ IntPtr @callback,
+ IntPtr @callbackData
+ );
+
+ [DllImport("livekit_uniffi", CallingConvention = CallingConvention.Cdecl)]
+ public static extern void ffi_livekit_uniffi_rust_future_cancel_pointer(IntPtr @handle);
+
+ [DllImport("livekit_uniffi", CallingConvention = CallingConvention.Cdecl)]
+ public static extern void ffi_livekit_uniffi_rust_future_free_pointer(IntPtr @handle);
+
+ [DllImport("livekit_uniffi", CallingConvention = CallingConvention.Cdecl)]
+ public static extern IntPtr ffi_livekit_uniffi_rust_future_complete_pointer(
+ IntPtr @handle,
+ ref UniffiRustCallStatus _uniffi_out_err
+ );
+
+ [DllImport("livekit_uniffi", CallingConvention = CallingConvention.Cdecl)]
+ public static extern void ffi_livekit_uniffi_rust_future_poll_rust_buffer(
+ IntPtr @handle,
+ IntPtr @callback,
+ IntPtr @callbackData
+ );
+
+ [DllImport("livekit_uniffi", CallingConvention = CallingConvention.Cdecl)]
+ public static extern void ffi_livekit_uniffi_rust_future_cancel_rust_buffer(IntPtr @handle);
+
+ [DllImport("livekit_uniffi", CallingConvention = CallingConvention.Cdecl)]
+ public static extern void ffi_livekit_uniffi_rust_future_free_rust_buffer(IntPtr @handle);
+
+ [DllImport("livekit_uniffi", CallingConvention = CallingConvention.Cdecl)]
+ public static extern RustBuffer ffi_livekit_uniffi_rust_future_complete_rust_buffer(
+ IntPtr @handle,
+ ref UniffiRustCallStatus _uniffi_out_err
+ );
+
+ [DllImport("livekit_uniffi", CallingConvention = CallingConvention.Cdecl)]
+ public static extern void ffi_livekit_uniffi_rust_future_poll_void(
+ IntPtr @handle,
+ IntPtr @callback,
+ IntPtr @callbackData
+ );
+
+ [DllImport("livekit_uniffi", CallingConvention = CallingConvention.Cdecl)]
+ public static extern void ffi_livekit_uniffi_rust_future_cancel_void(IntPtr @handle);
+
+ [DllImport("livekit_uniffi", CallingConvention = CallingConvention.Cdecl)]
+ public static extern void ffi_livekit_uniffi_rust_future_free_void(IntPtr @handle);
+
+ [DllImport("livekit_uniffi", CallingConvention = CallingConvention.Cdecl)]
+ public static extern void ffi_livekit_uniffi_rust_future_complete_void(
+ IntPtr @handle,
+ ref UniffiRustCallStatus _uniffi_out_err
+ );
+
+ [DllImport("livekit_uniffi", CallingConvention = CallingConvention.Cdecl)]
+ public static extern ushort uniffi_livekit_uniffi_checksum_func_build_version();
+
+ [DllImport("livekit_uniffi", CallingConvention = CallingConvention.Cdecl)]
+ public static extern ushort uniffi_livekit_uniffi_checksum_func_generate_token();
+
+ [DllImport("livekit_uniffi", CallingConvention = CallingConvention.Cdecl)]
+ public static extern ushort uniffi_livekit_uniffi_checksum_func_log_forward_bootstrap();
+
+ [DllImport("livekit_uniffi", CallingConvention = CallingConvention.Cdecl)]
+ public static extern ushort uniffi_livekit_uniffi_checksum_func_log_forward_receive();
+
+ [DllImport("livekit_uniffi", CallingConvention = CallingConvention.Cdecl)]
+ public static extern ushort uniffi_livekit_uniffi_checksum_func_verify_token();
+
+ [DllImport("livekit_uniffi", CallingConvention = CallingConvention.Cdecl)]
+ public static extern uint ffi_livekit_uniffi_uniffi_contract_version();
+
+ static void uniffiCheckContractApiVersion()
+ {
+ var scaffolding_contract_version = _UniFFILib.ffi_livekit_uniffi_uniffi_contract_version();
+ if (29 != scaffolding_contract_version)
+ {
+ throw new UniffiContractVersionException(
+ $"uniffi.livekit_uniffi: uniffi bindings expected version `29`, library returned `{scaffolding_contract_version}`"
+ );
+ }
+ }
+
+ static void uniffiCheckApiChecksums()
+ {
+ {
+ var checksum = _UniFFILib.uniffi_livekit_uniffi_checksum_func_build_version();
+ if (checksum != 45072)
+ {
+ throw new UniffiContractChecksumException(
+ $"uniffi.livekit_uniffi: uniffi bindings expected function `uniffi_livekit_uniffi_checksum_func_build_version` checksum `45072`, library returned `{checksum}`"
+ );
+ }
+ }
+ {
+ var checksum = _UniFFILib.uniffi_livekit_uniffi_checksum_func_generate_token();
+ if (checksum != 29823)
+ {
+ throw new UniffiContractChecksumException(
+ $"uniffi.livekit_uniffi: uniffi bindings expected function `uniffi_livekit_uniffi_checksum_func_generate_token` checksum `29823`, library returned `{checksum}`"
+ );
+ }
+ }
+ {
+ var checksum = _UniFFILib.uniffi_livekit_uniffi_checksum_func_log_forward_bootstrap();
+ if (checksum != 28675)
+ {
+ throw new UniffiContractChecksumException(
+ $"uniffi.livekit_uniffi: uniffi bindings expected function `uniffi_livekit_uniffi_checksum_func_log_forward_bootstrap` checksum `28675`, library returned `{checksum}`"
+ );
+ }
+ }
+ {
+ var checksum = _UniFFILib.uniffi_livekit_uniffi_checksum_func_log_forward_receive();
+ if (checksum != 7863)
+ {
+ throw new UniffiContractChecksumException(
+ $"uniffi.livekit_uniffi: uniffi bindings expected function `uniffi_livekit_uniffi_checksum_func_log_forward_receive` checksum `7863`, library returned `{checksum}`"
+ );
+ }
+ }
+ {
+ var checksum = _UniFFILib.uniffi_livekit_uniffi_checksum_func_verify_token();
+ if (checksum != 47517)
+ {
+ throw new UniffiContractChecksumException(
+ $"uniffi.livekit_uniffi: uniffi bindings expected function `uniffi_livekit_uniffi_checksum_func_verify_token` checksum `47517`, library returned `{checksum}`"
+ );
+ }
+ }
+ }
+}
+
+// Public interface members begin here.
+
+#pragma warning disable 8625
+
+class FfiConverterUInt32 : FfiConverter
+{
+ public static FfiConverterUInt32 INSTANCE = new FfiConverterUInt32();
+
+ public override uint Lift(uint value)
+ {
+ return value;
+ }
+
+ public override uint Read(BigEndianStream stream)
+ {
+ return stream.ReadUInt();
+ }
+
+ public override uint Lower(uint value)
+ {
+ return value;
+ }
+
+ public override int AllocationSize(uint value)
+ {
+ return 4;
+ }
+
+ public override void Write(uint value, BigEndianStream stream)
+ {
+ stream.WriteUInt(value);
+ }
+}
+
+class FfiConverterUInt64 : FfiConverter
+{
+ public static FfiConverterUInt64 INSTANCE = new FfiConverterUInt64();
+
+ public override ulong Lift(ulong value)
+ {
+ return value;
+ }
+
+ public override ulong Read(BigEndianStream stream)
+ {
+ return stream.ReadULong();
+ }
+
+ public override ulong Lower(ulong value)
+ {
+ return value;
+ }
+
+ public override int AllocationSize(ulong value)
+ {
+ return 8;
+ }
+
+ public override void Write(ulong value, BigEndianStream stream)
+ {
+ stream.WriteULong(value);
+ }
+}
+
+class FfiConverterBoolean : FfiConverter
+{
+ public static FfiConverterBoolean INSTANCE = new FfiConverterBoolean();
+
+ public override bool Lift(sbyte value)
+ {
+ return value != 0;
+ }
+
+ public override bool Read(BigEndianStream stream)
+ {
+ return Lift(stream.ReadSByte());
+ }
+
+ public override sbyte Lower(bool value)
+ {
+ return value ? (sbyte)1 : (sbyte)0;
+ }
+
+ public override int AllocationSize(bool value)
+ {
+ return (sbyte)1;
+ }
+
+ public override void Write(bool value, BigEndianStream stream)
+ {
+ stream.WriteSByte(Lower(value));
+ }
+}
+
+class FfiConverterString : FfiConverter
+{
+ public static FfiConverterString INSTANCE = new FfiConverterString();
+
+ // 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.
+ public override string Lift(RustBuffer value)
+ {
+ try
+ {
+ var bytes = value.AsStream().ReadBytes(Convert.ToInt32(value.len));
+ return System.Text.Encoding.UTF8.GetString(bytes);
+ }
+ finally
+ {
+ RustBuffer.Free(value);
+ }
+ }
+
+ public override string Read(BigEndianStream stream)
+ {
+ var length = stream.ReadInt();
+ var bytes = stream.ReadBytes(length);
+ return System.Text.Encoding.UTF8.GetString(bytes);
+ }
+
+ public override RustBuffer Lower(string value)
+ {
+ var bytes = System.Text.Encoding.UTF8.GetBytes(value);
+ var rbuf = RustBuffer.Alloc(bytes.Length);
+ rbuf.AsWriteableStream().WriteBytes(bytes);
+ return rbuf;
+ }
+
+ // TODO(CS)
+ // We aren't sure exactly how many bytes our string will be once it's UTF-8
+ // encoded. Allocate 3 bytes per unicode codepoint which will always be
+ // enough.
+ public override int AllocationSize(string value)
+ {
+ const int sizeForLength = 4;
+ var sizeForString = System.Text.Encoding.UTF8.GetByteCount(value);
+ return sizeForLength + sizeForString;
+ }
+
+ public override void Write(string value, BigEndianStream stream)
+ {
+ var bytes = System.Text.Encoding.UTF8.GetBytes(value);
+ stream.WriteInt(bytes.Length);
+ stream.WriteBytes(bytes);
+ }
+}
+
+class FfiConverterDuration : FfiConverterRustBuffer
+{
+ public static FfiConverterDuration INSTANCE = new FfiConverterDuration();
+
+ // https://github.com/dotnet/runtime/blob/main/src/libraries/System.Private.CoreLib/src/System/TimeSpan.cs
+ private const uint NanosecondsPerTick = 100;
+
+ public override TimeSpan Read(BigEndianStream stream)
+ {
+ var seconds = stream.ReadULong();
+ var nanoseconds = stream.ReadUInt();
+ var ticks = seconds * TimeSpan.TicksPerSecond;
+ ticks += nanoseconds / NanosecondsPerTick;
+ return new TimeSpan(Convert.ToInt64(ticks));
+ }
+
+ public override int AllocationSize(TimeSpan value)
+ {
+ // 8 bytes for seconds, 4 bytes for nanoseconds
+ return 12;
+ }
+
+ public override void Write(TimeSpan value, BigEndianStream stream)
+ {
+ stream.WriteULong(Convert.ToUInt64(value.Ticks / TimeSpan.TicksPerSecond));
+ stream.WriteUInt(
+ Convert.ToUInt32(value.Ticks % TimeSpan.TicksPerSecond * NanosecondsPerTick)
+ );
+ }
+}
+
+///
+/// API credentials for access token generation and verification.
+///
+internal record ApiCredentials(string @key, string @secret) { }
+
+class FfiConverterTypeApiCredentials : FfiConverterRustBuffer
+{
+ public static FfiConverterTypeApiCredentials INSTANCE = new FfiConverterTypeApiCredentials();
+
+ public override ApiCredentials Read(BigEndianStream stream)
+ {
+ return new ApiCredentials(
+ @key: FfiConverterString.INSTANCE.Read(stream),
+ @secret: FfiConverterString.INSTANCE.Read(stream)
+ );
+ }
+
+ public override int AllocationSize(ApiCredentials value)
+ {
+ return 0
+ + FfiConverterString.INSTANCE.AllocationSize(value.@key)
+ + FfiConverterString.INSTANCE.AllocationSize(value.@secret);
+ }
+
+ public override void Write(ApiCredentials value, BigEndianStream stream)
+ {
+ FfiConverterString.INSTANCE.Write(value.@key, stream);
+ FfiConverterString.INSTANCE.Write(value.@secret, stream);
+ }
+}
+
+///
+/// Claims decoded from a valid access token.
+///
+internal record Claims(
+ ulong @exp,
+ string @iss,
+ ulong @nbf,
+ string @sub,
+ string @name,
+ VideoGrants @video,
+ SipGrants @sip,
+ string @sha256,
+ string @metadata,
+ Dictionary @attributes,
+ string @roomName
+) { }
+
+class FfiConverterTypeClaims : FfiConverterRustBuffer
+{
+ public static FfiConverterTypeClaims INSTANCE = new FfiConverterTypeClaims();
+
+ public override Claims Read(BigEndianStream stream)
+ {
+ return new Claims(
+ @exp: FfiConverterUInt64.INSTANCE.Read(stream),
+ @iss: FfiConverterString.INSTANCE.Read(stream),
+ @nbf: FfiConverterUInt64.INSTANCE.Read(stream),
+ @sub: FfiConverterString.INSTANCE.Read(stream),
+ @name: FfiConverterString.INSTANCE.Read(stream),
+ @video: FfiConverterTypeVideoGrants.INSTANCE.Read(stream),
+ @sip: FfiConverterTypeSIPGrants.INSTANCE.Read(stream),
+ @sha256: FfiConverterString.INSTANCE.Read(stream),
+ @metadata: FfiConverterString.INSTANCE.Read(stream),
+ @attributes: FfiConverterDictionaryStringString.INSTANCE.Read(stream),
+ @roomName: FfiConverterString.INSTANCE.Read(stream)
+ );
+ }
+
+ public override int AllocationSize(Claims value)
+ {
+ return 0
+ + FfiConverterUInt64.INSTANCE.AllocationSize(value.@exp)
+ + FfiConverterString.INSTANCE.AllocationSize(value.@iss)
+ + FfiConverterUInt64.INSTANCE.AllocationSize(value.@nbf)
+ + FfiConverterString.INSTANCE.AllocationSize(value.@sub)
+ + FfiConverterString.INSTANCE.AllocationSize(value.@name)
+ + FfiConverterTypeVideoGrants.INSTANCE.AllocationSize(value.@video)
+ + FfiConverterTypeSIPGrants.INSTANCE.AllocationSize(value.@sip)
+ + FfiConverterString.INSTANCE.AllocationSize(value.@sha256)
+ + FfiConverterString.INSTANCE.AllocationSize(value.@metadata)
+ + FfiConverterDictionaryStringString.INSTANCE.AllocationSize(value.@attributes)
+ + FfiConverterString.INSTANCE.AllocationSize(value.@roomName);
+ }
+
+ public override void Write(Claims value, BigEndianStream stream)
+ {
+ FfiConverterUInt64.INSTANCE.Write(value.@exp, stream);
+ FfiConverterString.INSTANCE.Write(value.@iss, stream);
+ FfiConverterUInt64.INSTANCE.Write(value.@nbf, stream);
+ FfiConverterString.INSTANCE.Write(value.@sub, stream);
+ FfiConverterString.INSTANCE.Write(value.@name, stream);
+ FfiConverterTypeVideoGrants.INSTANCE.Write(value.@video, stream);
+ FfiConverterTypeSIPGrants.INSTANCE.Write(value.@sip, stream);
+ FfiConverterString.INSTANCE.Write(value.@sha256, stream);
+ FfiConverterString.INSTANCE.Write(value.@metadata, stream);
+ FfiConverterDictionaryStringString.INSTANCE.Write(value.@attributes, stream);
+ FfiConverterString.INSTANCE.Write(value.@roomName, stream);
+ }
+}
+
+internal record LogForwardEntry(
+ LogForwardLevel @level,
+ string @target,
+ string? @file,
+ uint? @line,
+ string @message
+) { }
+
+class FfiConverterTypeLogForwardEntry : FfiConverterRustBuffer
+{
+ public static FfiConverterTypeLogForwardEntry INSTANCE = new FfiConverterTypeLogForwardEntry();
+
+ public override LogForwardEntry Read(BigEndianStream stream)
+ {
+ return new LogForwardEntry(
+ @level: FfiConverterTypeLogForwardLevel.INSTANCE.Read(stream),
+ @target: FfiConverterString.INSTANCE.Read(stream),
+ @file: FfiConverterOptionalString.INSTANCE.Read(stream),
+ @line: FfiConverterOptionalUInt32.INSTANCE.Read(stream),
+ @message: FfiConverterString.INSTANCE.Read(stream)
+ );
+ }
+
+ public override int AllocationSize(LogForwardEntry value)
+ {
+ return 0
+ + FfiConverterTypeLogForwardLevel.INSTANCE.AllocationSize(value.@level)
+ + FfiConverterString.INSTANCE.AllocationSize(value.@target)
+ + FfiConverterOptionalString.INSTANCE.AllocationSize(value.@file)
+ + FfiConverterOptionalUInt32.INSTANCE.AllocationSize(value.@line)
+ + FfiConverterString.INSTANCE.AllocationSize(value.@message);
+ }
+
+ public override void Write(LogForwardEntry value, BigEndianStream stream)
+ {
+ FfiConverterTypeLogForwardLevel.INSTANCE.Write(value.@level, stream);
+ FfiConverterString.INSTANCE.Write(value.@target, stream);
+ FfiConverterOptionalString.INSTANCE.Write(value.@file, stream);
+ FfiConverterOptionalUInt32.INSTANCE.Write(value.@line, stream);
+ FfiConverterString.INSTANCE.Write(value.@message, stream);
+ }
+}
+
+///
+/// SIP grants
+///
+/// Maps to the JWT's `sip` field.
+///
+internal record SipGrants(bool @admin, bool @call) { }
+
+class FfiConverterTypeSIPGrants : FfiConverterRustBuffer
+{
+ public static FfiConverterTypeSIPGrants INSTANCE = new FfiConverterTypeSIPGrants();
+
+ public override SipGrants Read(BigEndianStream stream)
+ {
+ return new SipGrants(
+ @admin: FfiConverterBoolean.INSTANCE.Read(stream),
+ @call: FfiConverterBoolean.INSTANCE.Read(stream)
+ );
+ }
+
+ public override int AllocationSize(SipGrants value)
+ {
+ return 0
+ + FfiConverterBoolean.INSTANCE.AllocationSize(value.@admin)
+ + FfiConverterBoolean.INSTANCE.AllocationSize(value.@call);
+ }
+
+ public override void Write(SipGrants value, BigEndianStream stream)
+ {
+ FfiConverterBoolean.INSTANCE.Write(value.@admin, stream);
+ FfiConverterBoolean.INSTANCE.Write(value.@call, stream);
+ }
+}
+
+///
+/// Options used for generating an access token.
+///
+/// Any fields left empty will use the token generator's defaults.
+///
+internal record TokenOptions(
+ TimeSpan? @ttl,
+ VideoGrants? @videoGrants,
+ SipGrants? @sipGrants,
+ string? @identity,
+ string? @name,
+ string? @metadata,
+ Dictionary? @attributes,
+ string? @sha256,
+ string? @roomName
+) { }
+
+class FfiConverterTypeTokenOptions : FfiConverterRustBuffer
+{
+ public static FfiConverterTypeTokenOptions INSTANCE = new FfiConverterTypeTokenOptions();
+
+ public override TokenOptions Read(BigEndianStream stream)
+ {
+ return new TokenOptions(
+ @ttl: FfiConverterOptionalDuration.INSTANCE.Read(stream),
+ @videoGrants: FfiConverterOptionalTypeVideoGrants.INSTANCE.Read(stream),
+ @sipGrants: FfiConverterOptionalTypeSIPGrants.INSTANCE.Read(stream),
+ @identity: FfiConverterOptionalString.INSTANCE.Read(stream),
+ @name: FfiConverterOptionalString.INSTANCE.Read(stream),
+ @metadata: FfiConverterOptionalString.INSTANCE.Read(stream),
+ @attributes: FfiConverterOptionalDictionaryStringString.INSTANCE.Read(stream),
+ @sha256: FfiConverterOptionalString.INSTANCE.Read(stream),
+ @roomName: FfiConverterOptionalString.INSTANCE.Read(stream)
+ );
+ }
+
+ public override int AllocationSize(TokenOptions value)
+ {
+ return 0
+ + FfiConverterOptionalDuration.INSTANCE.AllocationSize(value.@ttl)
+ + FfiConverterOptionalTypeVideoGrants.INSTANCE.AllocationSize(value.@videoGrants)
+ + FfiConverterOptionalTypeSIPGrants.INSTANCE.AllocationSize(value.@sipGrants)
+ + FfiConverterOptionalString.INSTANCE.AllocationSize(value.@identity)
+ + FfiConverterOptionalString.INSTANCE.AllocationSize(value.@name)
+ + FfiConverterOptionalString.INSTANCE.AllocationSize(value.@metadata)
+ + FfiConverterOptionalDictionaryStringString.INSTANCE.AllocationSize(value.@attributes)
+ + FfiConverterOptionalString.INSTANCE.AllocationSize(value.@sha256)
+ + FfiConverterOptionalString.INSTANCE.AllocationSize(value.@roomName);
+ }
+
+ public override void Write(TokenOptions value, BigEndianStream stream)
+ {
+ FfiConverterOptionalDuration.INSTANCE.Write(value.@ttl, stream);
+ FfiConverterOptionalTypeVideoGrants.INSTANCE.Write(value.@videoGrants, stream);
+ FfiConverterOptionalTypeSIPGrants.INSTANCE.Write(value.@sipGrants, stream);
+ FfiConverterOptionalString.INSTANCE.Write(value.@identity, stream);
+ FfiConverterOptionalString.INSTANCE.Write(value.@name, stream);
+ FfiConverterOptionalString.INSTANCE.Write(value.@metadata, stream);
+ FfiConverterOptionalDictionaryStringString.INSTANCE.Write(value.@attributes, stream);
+ FfiConverterOptionalString.INSTANCE.Write(value.@sha256, stream);
+ FfiConverterOptionalString.INSTANCE.Write(value.@roomName, stream);
+ }
+}
+
+///
+/// Room permissions
+///
+/// Maps to the JWT's `video` field.
+///
+internal record VideoGrants(
+ bool @roomCreate,
+ bool @roomList,
+ bool @roomRecord,
+ bool @roomAdmin,
+ bool @roomJoin,
+ string @room,
+ string @destinationRoom,
+ bool @canPublish,
+ bool @canSubscribe,
+ bool @canPublishData,
+ string[] @canPublishSources,
+ bool @canUpdateOwnMetadata,
+ bool @ingressAdmin,
+ bool @hidden,
+ bool @recorder
+) { }
+
+class FfiConverterTypeVideoGrants : FfiConverterRustBuffer
+{
+ public static FfiConverterTypeVideoGrants INSTANCE = new FfiConverterTypeVideoGrants();
+
+ public override VideoGrants Read(BigEndianStream stream)
+ {
+ return new VideoGrants(
+ @roomCreate: FfiConverterBoolean.INSTANCE.Read(stream),
+ @roomList: FfiConverterBoolean.INSTANCE.Read(stream),
+ @roomRecord: FfiConverterBoolean.INSTANCE.Read(stream),
+ @roomAdmin: FfiConverterBoolean.INSTANCE.Read(stream),
+ @roomJoin: FfiConverterBoolean.INSTANCE.Read(stream),
+ @room: FfiConverterString.INSTANCE.Read(stream),
+ @destinationRoom: FfiConverterString.INSTANCE.Read(stream),
+ @canPublish: FfiConverterBoolean.INSTANCE.Read(stream),
+ @canSubscribe: FfiConverterBoolean.INSTANCE.Read(stream),
+ @canPublishData: FfiConverterBoolean.INSTANCE.Read(stream),
+ @canPublishSources: FfiConverterSequenceString.INSTANCE.Read(stream),
+ @canUpdateOwnMetadata: FfiConverterBoolean.INSTANCE.Read(stream),
+ @ingressAdmin: FfiConverterBoolean.INSTANCE.Read(stream),
+ @hidden: FfiConverterBoolean.INSTANCE.Read(stream),
+ @recorder: FfiConverterBoolean.INSTANCE.Read(stream)
+ );
+ }
+
+ public override int AllocationSize(VideoGrants value)
+ {
+ return 0
+ + FfiConverterBoolean.INSTANCE.AllocationSize(value.@roomCreate)
+ + FfiConverterBoolean.INSTANCE.AllocationSize(value.@roomList)
+ + FfiConverterBoolean.INSTANCE.AllocationSize(value.@roomRecord)
+ + FfiConverterBoolean.INSTANCE.AllocationSize(value.@roomAdmin)
+ + FfiConverterBoolean.INSTANCE.AllocationSize(value.@roomJoin)
+ + FfiConverterString.INSTANCE.AllocationSize(value.@room)
+ + FfiConverterString.INSTANCE.AllocationSize(value.@destinationRoom)
+ + FfiConverterBoolean.INSTANCE.AllocationSize(value.@canPublish)
+ + FfiConverterBoolean.INSTANCE.AllocationSize(value.@canSubscribe)
+ + FfiConverterBoolean.INSTANCE.AllocationSize(value.@canPublishData)
+ + FfiConverterSequenceString.INSTANCE.AllocationSize(value.@canPublishSources)
+ + FfiConverterBoolean.INSTANCE.AllocationSize(value.@canUpdateOwnMetadata)
+ + FfiConverterBoolean.INSTANCE.AllocationSize(value.@ingressAdmin)
+ + FfiConverterBoolean.INSTANCE.AllocationSize(value.@hidden)
+ + FfiConverterBoolean.INSTANCE.AllocationSize(value.@recorder);
+ }
+
+ public override void Write(VideoGrants value, BigEndianStream stream)
+ {
+ FfiConverterBoolean.INSTANCE.Write(value.@roomCreate, stream);
+ FfiConverterBoolean.INSTANCE.Write(value.@roomList, stream);
+ FfiConverterBoolean.INSTANCE.Write(value.@roomRecord, stream);
+ FfiConverterBoolean.INSTANCE.Write(value.@roomAdmin, stream);
+ FfiConverterBoolean.INSTANCE.Write(value.@roomJoin, stream);
+ FfiConverterString.INSTANCE.Write(value.@room, stream);
+ FfiConverterString.INSTANCE.Write(value.@destinationRoom, stream);
+ FfiConverterBoolean.INSTANCE.Write(value.@canPublish, stream);
+ FfiConverterBoolean.INSTANCE.Write(value.@canSubscribe, stream);
+ FfiConverterBoolean.INSTANCE.Write(value.@canPublishData, stream);
+ FfiConverterSequenceString.INSTANCE.Write(value.@canPublishSources, stream);
+ FfiConverterBoolean.INSTANCE.Write(value.@canUpdateOwnMetadata, stream);
+ FfiConverterBoolean.INSTANCE.Write(value.@ingressAdmin, stream);
+ FfiConverterBoolean.INSTANCE.Write(value.@hidden, stream);
+ FfiConverterBoolean.INSTANCE.Write(value.@recorder, stream);
+ }
+}
+
+///
+/// An error that can occur during token generation or verification.
+///
+internal class AccessTokenException : UniffiException
+{
+ AccessTokenException(string message)
+ : base(message) { }
+
+ // Each variant is a nested class
+ // Flat enums carries a string error message, so no special implementation is necessary.
+
+ public class InvalidKeys : AccessTokenException
+ {
+ public InvalidKeys(string message)
+ : base(message) { }
+ }
+
+ public class InvalidEnv : AccessTokenException
+ {
+ public InvalidEnv(string message)
+ : base(message) { }
+ }
+
+ public class InvalidClaims : AccessTokenException
+ {
+ public InvalidClaims(string message)
+ : base(message) { }
+ }
+
+ public class Encoding : AccessTokenException
+ {
+ public Encoding(string message)
+ : base(message) { }
+ }
+}
+
+class FfiConverterTypeAccessTokenError
+ : FfiConverterRustBuffer,
+ CallStatusErrorHandler
+{
+ public static FfiConverterTypeAccessTokenError INSTANCE =
+ new FfiConverterTypeAccessTokenError();
+
+ public override AccessTokenException Read(BigEndianStream stream)
+ {
+ var value = stream.ReadInt();
+ switch (value)
+ {
+ case 1:
+ return new AccessTokenException.InvalidKeys(
+ FfiConverterString.INSTANCE.Read(stream)
+ );
+ case 2:
+ return new AccessTokenException.InvalidEnv(
+ FfiConverterString.INSTANCE.Read(stream)
+ );
+ case 3:
+ return new AccessTokenException.InvalidClaims(
+ FfiConverterString.INSTANCE.Read(stream)
+ );
+ case 4:
+ return new AccessTokenException.Encoding(FfiConverterString.INSTANCE.Read(stream));
+ default:
+ throw new InternalException(
+ String.Format(
+ "invalid error value '{0}' in FfiConverterTypeAccessTokenError.Read()",
+ value
+ )
+ );
+ }
+ }
+
+ public override int AllocationSize(AccessTokenException value)
+ {
+ return 4 + FfiConverterString.INSTANCE.AllocationSize(value.Message);
+ }
+
+ public override void Write(AccessTokenException value, BigEndianStream stream)
+ {
+ switch (value)
+ {
+ case AccessTokenException.InvalidKeys:
+ stream.WriteInt(1);
+ break;
+ case AccessTokenException.InvalidEnv:
+ stream.WriteInt(2);
+ break;
+ case AccessTokenException.InvalidClaims:
+ stream.WriteInt(3);
+ break;
+ case AccessTokenException.Encoding:
+ stream.WriteInt(4);
+ break;
+ default:
+ throw new InternalException(
+ String.Format(
+ "invalid error value '{0}' in FfiConverterTypeAccessTokenError.Write()",
+ value
+ )
+ );
+ }
+ }
+}
+
+internal enum LogForwardFilter : int
+{
+ Off,
+ Error,
+ Warn,
+ Info,
+ Debug,
+ Trace,
+}
+
+class FfiConverterTypeLogForwardFilter : FfiConverterRustBuffer
+{
+ public static FfiConverterTypeLogForwardFilter INSTANCE =
+ new FfiConverterTypeLogForwardFilter();
+
+ public override LogForwardFilter Read(BigEndianStream stream)
+ {
+ var value = stream.ReadInt() - 1;
+ if (Enum.IsDefined(typeof(LogForwardFilter), value))
+ {
+ return (LogForwardFilter)value;
+ }
+ else
+ {
+ throw new InternalException(
+ String.Format(
+ "invalid enum value '{0}' in FfiConverterTypeLogForwardFilter.Read()",
+ value
+ )
+ );
+ }
+ }
+
+ public override int AllocationSize(LogForwardFilter value)
+ {
+ return 4;
+ }
+
+ public override void Write(LogForwardFilter value, BigEndianStream stream)
+ {
+ stream.WriteInt((int)value + 1);
+ }
+}
+
+internal enum LogForwardLevel : int
+{
+ Error,
+ Warn,
+ Info,
+ Debug,
+ Trace,
+}
+
+class FfiConverterTypeLogForwardLevel : FfiConverterRustBuffer
+{
+ public static FfiConverterTypeLogForwardLevel INSTANCE = new FfiConverterTypeLogForwardLevel();
+
+ public override LogForwardLevel Read(BigEndianStream stream)
+ {
+ var value = stream.ReadInt() - 1;
+ if (Enum.IsDefined(typeof(LogForwardLevel), value))
+ {
+ return (LogForwardLevel)value;
+ }
+ else
+ {
+ throw new InternalException(
+ String.Format(
+ "invalid enum value '{0}' in FfiConverterTypeLogForwardLevel.Read()",
+ value
+ )
+ );
+ }
+ }
+
+ public override int AllocationSize(LogForwardLevel value)
+ {
+ return 4;
+ }
+
+ public override void Write(LogForwardLevel value, BigEndianStream stream)
+ {
+ stream.WriteInt((int)value + 1);
+ }
+}
+
+class FfiConverterOptionalUInt32 : FfiConverterRustBuffer
+{
+ public static FfiConverterOptionalUInt32 INSTANCE = new FfiConverterOptionalUInt32();
+
+ public override uint? Read(BigEndianStream stream)
+ {
+ if (stream.ReadByte() == 0)
+ {
+ return null;
+ }
+ return FfiConverterUInt32.INSTANCE.Read(stream);
+ }
+
+ public override int AllocationSize(uint? value)
+ {
+ if (value == null)
+ {
+ return 1;
+ }
+ else
+ {
+ return 1 + FfiConverterUInt32.INSTANCE.AllocationSize((uint)value);
+ }
+ }
+
+ public override void Write(uint? value, BigEndianStream stream)
+ {
+ if (value == null)
+ {
+ stream.WriteByte(0);
+ }
+ else
+ {
+ stream.WriteByte(1);
+ FfiConverterUInt32.INSTANCE.Write((uint)value, stream);
+ }
+ }
+}
+
+class FfiConverterOptionalString : FfiConverterRustBuffer
+{
+ public static FfiConverterOptionalString INSTANCE = new FfiConverterOptionalString();
+
+ public override string? Read(BigEndianStream stream)
+ {
+ if (stream.ReadByte() == 0)
+ {
+ return null;
+ }
+ return FfiConverterString.INSTANCE.Read(stream);
+ }
+
+ public override int AllocationSize(string? value)
+ {
+ if (value == null)
+ {
+ return 1;
+ }
+ else
+ {
+ return 1 + FfiConverterString.INSTANCE.AllocationSize((string)value);
+ }
+ }
+
+ public override void Write(string? value, BigEndianStream stream)
+ {
+ if (value == null)
+ {
+ stream.WriteByte(0);
+ }
+ else
+ {
+ stream.WriteByte(1);
+ FfiConverterString.INSTANCE.Write((string)value, stream);
+ }
+ }
+}
+
+class FfiConverterOptionalDuration : FfiConverterRustBuffer
+{
+ public static FfiConverterOptionalDuration INSTANCE = new FfiConverterOptionalDuration();
+
+ public override TimeSpan? Read(BigEndianStream stream)
+ {
+ if (stream.ReadByte() == 0)
+ {
+ return null;
+ }
+ return FfiConverterDuration.INSTANCE.Read(stream);
+ }
+
+ public override int AllocationSize(TimeSpan? value)
+ {
+ if (value == null)
+ {
+ return 1;
+ }
+ else
+ {
+ return 1 + FfiConverterDuration.INSTANCE.AllocationSize((TimeSpan)value);
+ }
+ }
+
+ public override void Write(TimeSpan? value, BigEndianStream stream)
+ {
+ if (value == null)
+ {
+ stream.WriteByte(0);
+ }
+ else
+ {
+ stream.WriteByte(1);
+ FfiConverterDuration.INSTANCE.Write((TimeSpan)value, stream);
+ }
+ }
+}
+
+class FfiConverterOptionalTypeApiCredentials : FfiConverterRustBuffer
+{
+ public static FfiConverterOptionalTypeApiCredentials INSTANCE =
+ new FfiConverterOptionalTypeApiCredentials();
+
+ public override ApiCredentials? Read(BigEndianStream stream)
+ {
+ if (stream.ReadByte() == 0)
+ {
+ return null;
+ }
+ return FfiConverterTypeApiCredentials.INSTANCE.Read(stream);
+ }
+
+ public override int AllocationSize(ApiCredentials? value)
+ {
+ if (value == null)
+ {
+ return 1;
+ }
+ else
+ {
+ return 1
+ + FfiConverterTypeApiCredentials.INSTANCE.AllocationSize((ApiCredentials)value);
+ }
+ }
+
+ public override void Write(ApiCredentials? value, BigEndianStream stream)
+ {
+ if (value == null)
+ {
+ stream.WriteByte(0);
+ }
+ else
+ {
+ stream.WriteByte(1);
+ FfiConverterTypeApiCredentials.INSTANCE.Write((ApiCredentials)value, stream);
+ }
+ }
+}
+
+class FfiConverterOptionalTypeLogForwardEntry : FfiConverterRustBuffer
+{
+ public static FfiConverterOptionalTypeLogForwardEntry INSTANCE =
+ new FfiConverterOptionalTypeLogForwardEntry();
+
+ public override LogForwardEntry? Read(BigEndianStream stream)
+ {
+ if (stream.ReadByte() == 0)
+ {
+ return null;
+ }
+ return FfiConverterTypeLogForwardEntry.INSTANCE.Read(stream);
+ }
+
+ public override int AllocationSize(LogForwardEntry? value)
+ {
+ if (value == null)
+ {
+ return 1;
+ }
+ else
+ {
+ return 1
+ + FfiConverterTypeLogForwardEntry.INSTANCE.AllocationSize((LogForwardEntry)value);
+ }
+ }
+
+ public override void Write(LogForwardEntry? value, BigEndianStream stream)
+ {
+ if (value == null)
+ {
+ stream.WriteByte(0);
+ }
+ else
+ {
+ stream.WriteByte(1);
+ FfiConverterTypeLogForwardEntry.INSTANCE.Write((LogForwardEntry)value, stream);
+ }
+ }
+}
+
+class FfiConverterOptionalTypeSIPGrants : FfiConverterRustBuffer
+{
+ public static FfiConverterOptionalTypeSIPGrants INSTANCE =
+ new FfiConverterOptionalTypeSIPGrants();
+
+ public override SipGrants? Read(BigEndianStream stream)
+ {
+ if (stream.ReadByte() == 0)
+ {
+ return null;
+ }
+ return FfiConverterTypeSIPGrants.INSTANCE.Read(stream);
+ }
+
+ public override int AllocationSize(SipGrants? value)
+ {
+ if (value == null)
+ {
+ return 1;
+ }
+ else
+ {
+ return 1 + FfiConverterTypeSIPGrants.INSTANCE.AllocationSize((SipGrants)value);
+ }
+ }
+
+ public override void Write(SipGrants? value, BigEndianStream stream)
+ {
+ if (value == null)
+ {
+ stream.WriteByte(0);
+ }
+ else
+ {
+ stream.WriteByte(1);
+ FfiConverterTypeSIPGrants.INSTANCE.Write((SipGrants)value, stream);
+ }
+ }
+}
+
+class FfiConverterOptionalTypeVideoGrants : FfiConverterRustBuffer
+{
+ public static FfiConverterOptionalTypeVideoGrants INSTANCE =
+ new FfiConverterOptionalTypeVideoGrants();
+
+ public override VideoGrants? Read(BigEndianStream stream)
+ {
+ if (stream.ReadByte() == 0)
+ {
+ return null;
+ }
+ return FfiConverterTypeVideoGrants.INSTANCE.Read(stream);
+ }
+
+ public override int AllocationSize(VideoGrants? value)
+ {
+ if (value == null)
+ {
+ return 1;
+ }
+ else
+ {
+ return 1 + FfiConverterTypeVideoGrants.INSTANCE.AllocationSize((VideoGrants)value);
+ }
+ }
+
+ public override void Write(VideoGrants? value, BigEndianStream stream)
+ {
+ if (value == null)
+ {
+ stream.WriteByte(0);
+ }
+ else
+ {
+ stream.WriteByte(1);
+ FfiConverterTypeVideoGrants.INSTANCE.Write((VideoGrants)value, stream);
+ }
+ }
+}
+
+class FfiConverterOptionalDictionaryStringString
+ : FfiConverterRustBuffer?>
+{
+ public static FfiConverterOptionalDictionaryStringString INSTANCE =
+ new FfiConverterOptionalDictionaryStringString();
+
+ public override Dictionary? Read(BigEndianStream stream)
+ {
+ if (stream.ReadByte() == 0)
+ {
+ return null;
+ }
+ return FfiConverterDictionaryStringString.INSTANCE.Read(stream);
+ }
+
+ public override int AllocationSize(Dictionary? value)
+ {
+ if (value == null)
+ {
+ return 1;
+ }
+ else
+ {
+ return 1
+ + FfiConverterDictionaryStringString.INSTANCE.AllocationSize(
+ (Dictionary)value
+ );
+ }
+ }
+
+ public override void Write(Dictionary? value, BigEndianStream stream)
+ {
+ if (value == null)
+ {
+ stream.WriteByte(0);
+ }
+ else
+ {
+ stream.WriteByte(1);
+ FfiConverterDictionaryStringString.INSTANCE.Write(
+ (Dictionary)value,
+ stream
+ );
+ }
+ }
+}
+
+class FfiConverterSequenceString : FfiConverterRustBuffer
+{
+ public static FfiConverterSequenceString INSTANCE = new FfiConverterSequenceString();
+
+ public override string[] Read(BigEndianStream stream)
+ {
+ var length = stream.ReadInt();
+ if (length == 0)
+ {
+ return [];
+ }
+
+ var result = new string[(length)];
+ var readFn = FfiConverterString.INSTANCE.Read;
+ for (int i = 0; i < length; i++)
+ {
+ result[i] = readFn(stream);
+ }
+ return result;
+ }
+
+ public override int AllocationSize(string[] value)
+ {
+ var sizeForLength = 4;
+
+ // details/1-empty-list-as-default-method-parameter.md
+ if (value == null)
+ {
+ return sizeForLength;
+ }
+
+ var allocationSizeFn = FfiConverterString.INSTANCE.AllocationSize;
+ var sizeForItems = value.Sum(item => allocationSizeFn(item));
+ return sizeForLength + sizeForItems;
+ }
+
+ public override void Write(string[] value, BigEndianStream stream)
+ {
+ // details/1-empty-list-as-default-method-parameter.md
+ if (value == null)
+ {
+ stream.WriteInt(0);
+ return;
+ }
+
+ stream.WriteInt(value.Length);
+ var writerFn = FfiConverterString.INSTANCE.Write;
+ value.ForEach(item => writerFn(item, stream));
+ }
+}
+
+class FfiConverterDictionaryStringString : FfiConverterRustBuffer>
+{
+ public static FfiConverterDictionaryStringString INSTANCE =
+ new FfiConverterDictionaryStringString();
+
+ public override Dictionary Read(BigEndianStream stream)
+ {
+ var len = stream.ReadInt();
+ var result = new Dictionary(len);
+ var readerKey = FfiConverterString.INSTANCE.Read;
+ var readerValue = FfiConverterString.INSTANCE.Read;
+ for (int i = 0; i < len; i++)
+ {
+ var key = readerKey(stream);
+ var value = readerValue(stream);
+ result[key] = value;
+ }
+
+ return result;
+ }
+
+ public override int AllocationSize(Dictionary value)
+ {
+ var sizeForLength = 4;
+
+ // details/1-empty-list-as-default-method-parameter.md
+ if (value == null)
+ {
+ return sizeForLength;
+ }
+
+ var allocationKeySizeFn = FfiConverterString.INSTANCE.AllocationSize;
+ var allocationKValueSizeFn = FfiConverterString.INSTANCE.AllocationSize;
+ var sizeForItems = value.Sum(item =>
+ allocationKeySizeFn(item.Key) + allocationKValueSizeFn(item.Value)
+ );
+ return sizeForLength + sizeForItems;
+ }
+
+ public override void Write(Dictionary value, BigEndianStream stream)
+ {
+ // details/1-empty-list-as-default-method-parameter.md
+ if (value == null)
+ {
+ stream.WriteInt(0);
+ return;
+ }
+
+ stream.WriteInt(value.Count);
+ var writerKey = FfiConverterString.INSTANCE.Write;
+ var writerValue = FfiConverterString.INSTANCE.Write;
+ foreach (var item in value)
+ {
+ writerKey(item.Key, stream);
+ writerValue(item.Value, stream);
+ }
+ }
+}
+
+class ConcurrentHandleMap
+ where T : notnull
+{
+ Dictionary map = new Dictionary();
+
+ Object lock_ = new Object();
+ ulong currentHandle = 0;
+
+ public ulong Insert(T obj)
+ {
+ lock (lock_)
+ {
+ currentHandle += 1;
+ map[currentHandle] = obj;
+ return currentHandle;
+ }
+ }
+
+ public bool TryGet(ulong handle, out T result)
+ {
+ lock (lock_)
+ {
+#pragma warning disable 8601 // Possible null reference assignment
+ return map.TryGetValue(handle, out result);
+#pragma warning restore 8601
+ }
+ }
+
+ public T Get(ulong handle)
+ {
+ if (TryGet(handle, out var result))
+ {
+ return result;
+ }
+ else
+ {
+ throw new InternalException("ConcurrentHandleMap: Invalid handle");
+ }
+ }
+
+ public bool Remove(ulong handle)
+ {
+ return Remove(handle, out T result);
+ }
+
+ public bool Remove(ulong handle, out T result)
+ {
+ lock (lock_)
+ {
+ // Possible null reference assignment
+#pragma warning disable 8601
+ if (map.TryGetValue(handle, out result))
+ {
+#pragma warning restore 8601
+ map.Remove(handle);
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ }
+}
+
+[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+delegate void UniFfiFutureCallback(IntPtr continuationHandle, byte pollResult);
+
+internal static class _UniFFIAsync
+{
+ internal const byte UNIFFI_RUST_FUTURE_POLL_READY = 0;
+
+ // internal const byte UNIFFI_RUST_FUTURE_POLL_MAYBE_READY = 1;
+
+ internal static ConcurrentHandleMap> _async_handle_map =
+ new ConcurrentHandleMap>();
+ public static ConcurrentHandleMap _foreign_futures_map =
+ new ConcurrentHandleMap();
+
+ // FFI type for Rust future continuations
+ internal class UniffiRustFutureContinuationCallback
+ {
+ public static UniFfiFutureCallback callback = Callback;
+
+ public static void Callback(IntPtr continuationHandle, byte pollResult)
+ {
+ if (
+ _async_handle_map.Remove(
+ (ulong)continuationHandle.ToInt64(),
+ out TaskCompletionSource task
+ )
+ )
+ {
+ task.SetResult(pollResult);
+ }
+ else
+ {
+ throw new InternalException(
+ $"Unable to find continuation handle: {continuationHandle}"
+ );
+ }
+ }
+ }
+
+ public class UniffiForeignFutureFreeCallback
+ {
+ public static _UniFFILib.UniffiForeignFutureFree callback = Callback;
+
+ public static void Callback(ulong handle)
+ {
+ if (_foreign_futures_map.Remove(handle, out CancellationTokenSource task))
+ {
+ task.Cancel();
+ }
+ else
+ {
+ throw new InternalException($"Unable to find cancellation token: {handle}");
+ }
+ }
+ }
+
+ public delegate F CompleteFuncDelegate(IntPtr ptr, ref UniffiRustCallStatus status);
+
+ public delegate void CompleteActionDelegate(IntPtr ptr, ref UniffiRustCallStatus status);
+
+ private static async Task PollFuture(IntPtr rustFuture, Action pollFunc)
+ {
+ byte pollResult;
+ do
+ {
+ var tcs = new TaskCompletionSource(
+ TaskCreationOptions.RunContinuationsAsynchronously
+ );
+ IntPtr callback = Marshal.GetFunctionPointerForDelegate(
+ UniffiRustFutureContinuationCallback.callback
+ );
+ ulong mapEntry = _async_handle_map.Insert(tcs);
+ pollFunc(rustFuture, callback, (IntPtr)mapEntry);
+ pollResult = await tcs.Task;
+ } while (pollResult != UNIFFI_RUST_FUTURE_POLL_READY);
+ }
+
+ public static async Task UniffiRustCallAsync(
+ IntPtr rustFuture,
+ Action pollFunc,
+ CompleteFuncDelegate completeFunc,
+ Action freeFunc,
+ Func liftFunc,
+ CallStatusErrorHandler errorHandler
+ )
+ where E : UniffiException
+ {
+ try
+ {
+ await PollFuture(rustFuture, pollFunc);
+ var result = _UniffiHelpers.RustCallWithError(
+ errorHandler,
+ (ref UniffiRustCallStatus status) => completeFunc(rustFuture, ref status)
+ );
+ return liftFunc(result);
+ }
+ finally
+ {
+ freeFunc(rustFuture);
+ }
+ }
+
+ public static async Task UniffiRustCallAsync(
+ IntPtr rustFuture,
+ Action pollFunc,
+ CompleteActionDelegate completeFunc,
+ Action freeFunc,
+ CallStatusErrorHandler errorHandler
+ )
+ where E : UniffiException
+ {
+ try
+ {
+ await PollFuture(rustFuture, pollFunc);
+ _UniffiHelpers.RustCallWithError(
+ errorHandler,
+ (ref UniffiRustCallStatus status) => completeFunc(rustFuture, ref status)
+ );
+ }
+ finally
+ {
+ freeFunc(rustFuture);
+ }
+ }
+}
+#pragma warning restore 8625
+internal static class LivekitUniffiMethods
+{
+ ///
+ /// Returns the version specified in the crate's Cargo.toml.
+ ///
+ public static string BuildVersion()
+ {
+ return FfiConverterString.INSTANCE.Lift(
+ _UniffiHelpers.RustCall(
+ (ref UniffiRustCallStatus _status) =>
+ _UniFFILib.uniffi_livekit_uniffi_fn_func_build_version(ref _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.
+ ///
+ ///
+ public static string GenerateToken(TokenOptions @options, ApiCredentials? @credentials)
+ {
+ return FfiConverterString.INSTANCE.Lift(
+ _UniffiHelpers.RustCallWithError(
+ FfiConverterTypeAccessTokenError.INSTANCE,
+ (ref UniffiRustCallStatus _status) =>
+ _UniFFILib.uniffi_livekit_uniffi_fn_func_generate_token(
+ FfiConverterTypeTokenOptions.INSTANCE.Lower(@options),
+ FfiConverterOptionalTypeApiCredentials.INSTANCE.Lower(@credentials),
+ ref _status
+ )
+ )
+ );
+ }
+
+ ///
+ /// Bootstraps log forwarding.
+ ///
+ /// Generally, you will invoke this once early in program execution. However,
+ /// subsequent invocations are allowed to change the log level.
+ ///
+ public static void LogForwardBootstrap(LogForwardFilter @level)
+ {
+ _UniffiHelpers.RustCall(
+ (ref UniffiRustCallStatus _status) =>
+ _UniFFILib.uniffi_livekit_uniffi_fn_func_log_forward_bootstrap(
+ FfiConverterTypeLogForwardFilter.INSTANCE.Lower(@level),
+ ref _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.
+ ///
+ public static async Task LogForwardReceive()
+ {
+ return await _UniFFIAsync.UniffiRustCallAsync(
+ // Get rust future
+ _UniFFILib.uniffi_livekit_uniffi_fn_func_log_forward_receive(),
+ // Poll
+ (IntPtr future, IntPtr continuation, IntPtr data) =>
+ _UniFFILib.ffi_livekit_uniffi_rust_future_poll_rust_buffer(
+ future,
+ continuation,
+ data
+ ),
+ // Complete
+ (IntPtr future, ref UniffiRustCallStatus status) =>
+ {
+ return _UniFFILib.ffi_livekit_uniffi_rust_future_complete_rust_buffer(
+ future,
+ ref status
+ );
+ },
+ // Free
+ (IntPtr future) => _UniFFILib.ffi_livekit_uniffi_rust_future_free_rust_buffer(future),
+ // Lift
+ (result) => FfiConverterOptionalTypeLogForwardEntry.INSTANCE.Lift(result),
+ // Error
+ NullCallStatusErrorHandler.INSTANCE
+ );
+ }
+
+ ///
+ /// 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 static Claims VerifyToken(string @token, ApiCredentials? @credentials)
+ {
+ return FfiConverterTypeClaims.INSTANCE.Lift(
+ _UniffiHelpers.RustCallWithError(
+ FfiConverterTypeAccessTokenError.INSTANCE,
+ (ref UniffiRustCallStatus _status) =>
+ _UniFFILib.uniffi_livekit_uniffi_fn_func_verify_token(
+ FfiConverterString.INSTANCE.Lower(@token),
+ FfiConverterOptionalTypeApiCredentials.INSTANCE.Lower(@credentials),
+ ref _status
+ )
+ )
+ );
+ }
+}
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