Skip to content

Integrate initial uniffi rust core - #1160

Draft
1egoman wants to merge 3 commits into
mainfrom
uniffi-rust-core
Draft

Integrate initial uniffi rust core#1160
1egoman wants to merge 3 commits into
mainfrom
uniffi-rust-core

Conversation

@1egoman

@1egoman 1egoman commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Some work was recently done on the rust sdks repo to get a dart uniffi bindgen integrated into the livekit-uniffi crate - here's a pull request: livekit/rust-sdks#1183.

This is the other half of the change to integrate this these bindings into the flutter sdk. What this consisted of at a high level:

  • Fixed some dart bindgen bugs that were discovered when building the latest livekit-uniffi release containing data streams and data tracks.
  • Flutter native assets require at a minimum Flutter 3.38. So, I updated from flutter >=3.27.0 to >=3.38.0 / Dart >=3.10.0.
    • This is a significant version bump from what I can tell and some thorough testing should be done to ensure nothing was broken.
    • Also as part of this, the output of dart format changed to "tall style" (more info) - and as part of this, in a9ef3a6, I've been forced to reformat a lot of files. This was done mechanically by dart format, it shouldn't require an in depth review
  • Added in a facade layer to switch between native code (where the livekit-uniffi can be loaded successfully) and web where it cannot be.
    • The facade exposes LiveKitUniffi.isAvailable which can be used to guard uniffi code for future features
    • I've also taken the liberty of exposing the LiveKitUniffi.buildVersion version initially. This is a simple, sync call and should be a good proof of concept that everything is wired up properly

This change is a prerequisite to adding data streams v2 support to flutter.

Also note that this right now only builds locally. So CI fails and that is expected. Once all TODO items are complete, ci should build.

Warning

This pull request was largely LLM generated and while it has been reviewed by a human, that human is not a flutter expert. I have tested this and can confirm it works in the happy path, but no other validation has been done.

A more thorough review of this needs to occur from a domain expert before it could be merged.

TODO

  • Get pull requests to upstream uniffi-dart package merged.
    • If this doesn't happen in a timely manor, consider potentially migrating the personal fork I made to an official livekit maintained fork before merging this, or figuring out some other way around the problem (like a patching script that runs post bindgen, etc).
  • Get the livekit-uniffi dart bindings published to https://pub.dev/, and cut over to the production build when making production flutter sdk releases.
    • Right now, this pull request assumes they are all locally built and located in ../rust-sdks/livekit-uniffi/packages/dart.

Comment on lines 219 to 224

final ReceivedMessageContent content =
isLocalParticipant ? UserTranscript(displayContent) : AgentTranscript(displayContent);
final ReceivedMessageContent content = isLocalParticipant
? UserTranscript(displayContent)
: AgentTranscript(displayContent);

return ReceivedMessage(

@1egoman 1egoman Aug 7, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Image

Per the comment in the pull request body: the vast majority of this change is mechanical and can be ignored. In practice, it's more like a couple hundred lines of interesting stuff. Here's an example of the reformatting noise which is scoped to 5074c77.

Comment on lines +17 to +45
/// Facade over the Rust core exposed by the `livekit_uniffi` package.
///
/// `livekit_uniffi` reaches Rust through Dart's Native Assets: its build hook
/// bundles a `cdylib` into the host app and the generated bindings call into it
/// with `@Native`. None of that exists on the web, where there is no dynamic
/// library to load, so every entry point here is split native/web through the
/// same conditional-import pattern the rest of the SDK uses (see
/// `support/platform.dart`). Web builds must never reach the generated
/// bindings -- importing them at all would break `dart compile js`/`wasm`.
///
/// Callers get [isAvailable] to branch on, and platform-specific code paths
/// stay out of the public API surface.
abstract final class LiveKitUniffi {
/// Whether the Rust core can be called on this platform.
///
/// False on web. Every other member throws [UnsupportedError] when this is
/// false, rather than returning a silently wrong value.
static bool get isAvailable => impl.isAvailable;

/// Version string reported by the Rust core.
///
/// The simplest possible round trip -- a synchronous, argument-free call
/// returning a string -- so it doubles as the smoke test that the whole
/// chain is wired up: build hook resolved the library, `@Native` bound the
/// symbol, and a value came back across the FFI boundary.
///
/// Throws [UnsupportedError] on web.
static String get buildVersion => impl.buildVersion();
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here's the newly introduced LiveKitUniffi facade. This allows all these bits of functionality to be turned into noops on web.

Comment thread pubspec.yaml
Comment on lines 26 to +70
@@ -55,6 +57,17 @@ dependencies:
flutter_webrtc: 1.6.0
dart_webrtc: ^1.8.0

# Rust core (livekit-uniffi), delivered as a bundled cdylib via Native Assets.
# Native platforms only — see lib/src/uniffi/.
livekit_uniffi: ^0.1.7

# livekit_uniffi is not published to pub.dev yet, so it resolves out of a sibling
# rust-sdks checkout produced by `cargo make dart-package`. See AGENTS.md. Drop
# this once the package is published.
dependency_overrides:
livekit_uniffi:
path: ../rust-sdks/livekit-uniffi/packages/dart

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The version bump and some local packaging machinery.

Calling out again because it is very important: this CANNOT be merged in its current state until the flutter bindings are distributed somehow. From what I can tell looking at the rust half, it looks like what was being planned was to publish them to https://pub.dev.

1egoman added 3 commits August 7, 2026 16:30
Groundwork for delivering the Rust core through Dart's Native Assets,
which is only stable from Flutter 3.38 / Dart 3.10 onwards.

The newer language version turns on lints the tree does not yet satisfy:

- `*.g.dart` joins the analyzer exclusions. AGENTS.md already described
  json_serializable output as excluded, but only the protobuf patterns
  actually were; 47 of the 48 new `use_null_aware_elements` hits are in
  generated files nobody edits by hand.
- The remaining `use_null_aware_elements` hit, in `Room`, and four
  `unnecessary_underscores` hits in the RPC tests, are fixed directly.

Crossing Dart 3.7 also switches `dart format` to the tall style, which
reformats the whole tree. That is mechanical and lands separately, in the
commit that follows, so it does not bury this one. `dart format
--set-exit-if-changed` is therefore red at this commit and green again at
the next.

No functional change.
Pure output of `dart format .`. No functional or semantic change.

The formatter picks its style from the package language version, so the
SDK bump in the previous commit crosses Dart 3.7 and switches the whole
tree from the short style to the tall one. `dart format
--set-exit-if-changed` is CI-enforced, so this has to land -- it is split
out only so the bump and its lint fixes stay readable.

Reproduce with `dart format .` on the parent commit.
Establishes the development loop for calling into `livekit-uniffi` from
this SDK, and exercises it with `buildVersion()` -- a synchronous,
argument-free call returning a string, so a green test means the whole
chain is intact: the build hook resolved a cdylib for the target, Native
Assets bundled it, `@Native` bound the symbol, and a value crossed back.

`lib/src/uniffi/` splits native/web with the same conditional-import
pattern as the rest of the SDK. There is no dynamic library to load on
the web, so `uniffi_io.dart` is the only file permitted to import the
generated bindings -- reaching them from anywhere web-reachable pulls
`dart:ffi` into a web compile and breaks `flutter build web`/`--wasm`.
Callers branch on `LiveKitUniffi.isAvailable`. The facade is internal for
now; nothing is added to the public API surface.

`livekit_uniffi` is not on pub.dev, so both pubspecs override it to a
sibling rust-sdks checkout -- overrides do not propagate from a
dependency, hence both. Until it is published this branch cannot merge:
CI has no rust-sdks checkout, so `flutter pub get` will fail there.

Verified: 392 tests pass, web and wasm builds succeed, analyze and format
are clean.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant