From 36ed60d95c6761b4ea40016061aeb68c695c91b2 Mon Sep 17 00:00:00 2001 From: "Timo K." Date: Tue, 15 Sep 2026 19:06:04 +0200 Subject: [PATCH] plan oxidation - add the drivers - add the uniffi build toolchain - create the plan document --- .gitattributes | 3 + .oxfmtrc.json | 7 +- .oxlintrc.json | 3 + element-call-oxidation-plan.md | 730 ++ knip.ts | 9 + locales/en/app.json | 2 + package.json | 1 + pnpm-lock.yaml | 8 + scripts/sync-matrix-rtc-sdk.sh | 52 + src/driver/ElementCallMatrixClientDriver.ts | 161 + .../MockElementCallMatrixClientDriver.test.ts | 89 + .../MockElementCallMatrixClientDriver.ts | 246 + src/driver/MockRtcMatrixDriver.test.ts | 171 + src/driver/MockRtcMatrixDriver.ts | 676 ++ src/driver/RtcMatrixDriver.ts | 21 + ...JsSdkElementCallMatrixClientDriver.test.ts | 123 + .../JsSdkElementCallMatrixClientDriver.ts | 329 + src/driver/jsSdk/JsSdkRtcMatrixDriver.test.ts | 488 + src/driver/jsSdk/JsSdkRtcMatrixDriver.ts | 630 ++ src/driver/jsSdk/jsSdkTestFakes.ts | 150 + src/driver/observe.ts | 29 + src/matrix-rtc-sdk/generated/VERSION | 2 + .../generated/matrix_rtc-ffi.ts | 103 + src/matrix-rtc-sdk/generated/matrix_rtc.ts | 8716 +++++++++++++++++ .../generated/wasm-bindgen/index.d.ts | 30 + .../generated/wasm-bindgen/index.js | 3049 ++++++ .../generated/wasm-bindgen/index_bg.wasm | Bin 0 -> 1553078 bytes src/matrix-rtc-sdk/index.test.ts | 136 + src/matrix-rtc-sdk/index.ts | 90 + src/state/rtc/CallParticipation.test.ts | 393 + src/state/rtc/CallParticipation.ts | 494 + src/state/rtc/errors.ts | 67 + src/state/rtc/joinParams.ts | 104 + src/state/rtc/slot.ts | 19 + src/state/rtc/transportIntent.ts | 34 + src/utils/errors.ts | 16 + src/utils/test-matrix-rtc.ts | 31 + vitest.config.ts | 2 + 38 files changed, 17213 insertions(+), 1 deletion(-) create mode 100644 .gitattributes create mode 100644 element-call-oxidation-plan.md create mode 100755 scripts/sync-matrix-rtc-sdk.sh create mode 100644 src/driver/ElementCallMatrixClientDriver.ts create mode 100644 src/driver/MockElementCallMatrixClientDriver.test.ts create mode 100644 src/driver/MockElementCallMatrixClientDriver.ts create mode 100644 src/driver/MockRtcMatrixDriver.test.ts create mode 100644 src/driver/MockRtcMatrixDriver.ts create mode 100644 src/driver/RtcMatrixDriver.ts create mode 100644 src/driver/jsSdk/JsSdkElementCallMatrixClientDriver.test.ts create mode 100644 src/driver/jsSdk/JsSdkElementCallMatrixClientDriver.ts create mode 100644 src/driver/jsSdk/JsSdkRtcMatrixDriver.test.ts create mode 100644 src/driver/jsSdk/JsSdkRtcMatrixDriver.ts create mode 100644 src/driver/jsSdk/jsSdkTestFakes.ts create mode 100644 src/driver/observe.ts create mode 100644 src/matrix-rtc-sdk/generated/VERSION create mode 100644 src/matrix-rtc-sdk/generated/matrix_rtc-ffi.ts create mode 100644 src/matrix-rtc-sdk/generated/matrix_rtc.ts create mode 100644 src/matrix-rtc-sdk/generated/wasm-bindgen/index.d.ts create mode 100644 src/matrix-rtc-sdk/generated/wasm-bindgen/index.js create mode 100644 src/matrix-rtc-sdk/generated/wasm-bindgen/index_bg.wasm create mode 100644 src/matrix-rtc-sdk/index.test.ts create mode 100644 src/matrix-rtc-sdk/index.ts create mode 100644 src/state/rtc/CallParticipation.test.ts create mode 100644 src/state/rtc/CallParticipation.ts create mode 100644 src/state/rtc/errors.ts create mode 100644 src/state/rtc/joinParams.ts create mode 100644 src/state/rtc/slot.ts create mode 100644 src/state/rtc/transportIntent.ts create mode 100644 src/utils/test-matrix-rtc.ts diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 000000000..de8fcaf3d --- /dev/null +++ b/.gitattributes @@ -0,0 +1,3 @@ +# uniffi-generated MatrixRTC SDK bindings, vendored by scripts/sync-matrix-rtc-sdk.sh +src/matrix-rtc-sdk/generated/** linguist-generated=true +src/matrix-rtc-sdk/generated/**/*.wasm binary diff --git a/.oxfmtrc.json b/.oxfmtrc.json index 20bac1bf8..44be81943 100644 --- a/.oxfmtrc.json +++ b/.oxfmtrc.json @@ -2,5 +2,10 @@ "$schema": "./node_modules/oxfmt/configuration_schema.json", "printWidth": 80, "sortPackageJson": false, - "ignorePatterns": ["pnpm-lock.yaml", "node_modules", "dist"] + "ignorePatterns": [ + "pnpm-lock.yaml", + "node_modules", + "dist", + "src/matrix-rtc-sdk/generated" + ] } diff --git a/.oxlintrc.json b/.oxlintrc.json index c89ab8a28..cf1cef833 100644 --- a/.oxlintrc.json +++ b/.oxlintrc.json @@ -28,6 +28,9 @@ "env": { "builtin": true }, + // uniffi-generated bindings and wasm-bindgen glue, vendored by + // scripts/sync-matrix-rtc-sdk.sh; not ours to lint + "ignorePatterns": ["src/matrix-rtc-sdk/generated/**"], "rules": { "element-call/copyright-header": [ "error", diff --git a/element-call-oxidation-plan.md b/element-call-oxidation-plan.md new file mode 100644 index 000000000..e60ab4c74 --- /dev/null +++ b/element-call-oxidation-plan.md @@ -0,0 +1,730 @@ +# Element Call oxidation plan + +Move Element Call's MatrixRTC participation logic off `matrix-js-sdk`'s +`MatrixRTCSession` and onto the Rust `matrix-rtc` crate +(`~/Projects/matrix-rust-rtc/MatrixSdkArchitectureDraft`), consumed through its +uniffi wasm bindings. The Element Call **component** then depends on one +host-supplied object, a `MatrixDriver`, and never on a `MatrixClient`. The +standalone app and the widget become hosts like any other: they build a +`MatrixDriver` from their `matrix-js-sdk` client and hand it to the component. + +Revision 2 — incorporates the independent review (§10 lists what changed and +the assumptions taken where only the user can decide). + +Status legend: ☐ todo · ◐ in progress · ☑ done. + +**Where things stand (2026-09-14):** S0a, S0b, S1a, S1b and S2 are +implemented and green (`pnpm lint`, `pnpm format:check`, `pnpm test:unit`: +101 files / 785 tests). Nothing is committed yet, in either repository: the +crate changes (C2–C8; C1 was reverted in favour of slot opening; C11 and C12 done; +C9 and C10 are pending) sit uncommitted in +`~/Projects/matrix-rust-rtc/MatrixSdkArchitectureDraft`, and Element Call's +branch `toger5/oxidation` holds the vendored bindings, the driver layer +(`src/driver/**`), the participation layer (`src/state/rtc/**`) and the +config/lint changes. S3a is the next slice; its design is in §6 and the +files it touches are listed there. + +--- + +## 1. Goals and non-goals + +**Goals** + +1. `ElementCall` (component) takes `driver: MatrixDriver` instead of + `client: MatrixClient`. Nothing rendered under `CallView` imports + `MatrixClient`, `Room`, `RoomMember`, `MatrixEvent` or + `matrix-js-sdk/lib/matrixrtc`. +2. All MatrixRTC participation logic (session projection, own membership + join/leave/keep-alive, transport tokens, media key exchange) comes from the + crate's `FfiParticipationManager`. Element Call keeps only what the crate + deliberately leaves to the host: the LiveKit media plane, tiles, room + metadata, reactions, notifications, UI. +3. The standalone SPA, widget mode and `sdk/main.ts` construct a + `JsSdkMatrixDriver` (a port of the draft's `web-test-app/src/jsSdkDriver.ts` + that also works on js-sdk's `RoomWidgetClient`, extended with what Element + Call needs beyond RTC) and stop using `client.matrixRTC`. +4. Every existing gate stays green: `pnpm lint` (tsc, oxlint, knip, component + externals), `pnpm format:check`, `pnpm test` (unit + storybook), + `pnpm i18n:check`, all four builds, Playwright (standalone, widget, + component). + +**Non-goals** + +- Replacing `matrix-js-sdk` in the standalone shell (login, registration, room + creation, home page, crypto bootstrap). The shell keeps its client and wraps + it. `src/home/useGroupCallRooms.ts` stays on `client.matrixRTC` for now. +- Removing `matrix-js-sdk/lib/logger`. It is isolated behind + `src/utils/logger.ts` (S6) so a later swap is one line. +- Writing a matrix-rust-sdk-backed driver (Element X). The interface is shaped + so one can be written; none is written here. +- Publishing the crate as an npm package. Until it exists, the generated + bindings are vendored (§5.1). +- Turning on MSC4153 (cross-signed sender) enforcement. Parity first (§5.8). + +--- + +## 2. Where the code is today (inventory) + +Entry: `component/index.tsx` → `src/room/CallView.tsx` → `LobbyView` | +`ActiveCall` (`src/room/InCallView.tsx`) | `CallEndedView`. `ActiveCall` +builds the view model with +`createCallViewModel$(scope, rtcSession, matrixRoom, mediaDevices, muteStates, options, raisedHands$, reactions$, trackProcessorState$)`. + +| Concern | Files | js-sdk surface used | +| -------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Session memberships | `src/state/SessionBehaviors.ts`, `src/useMatrixRTCSessionMemberships.ts` | `rtcSession.memberships`, `MembershipsChanged`, `membership.getTransport`, `isKeyRotationSuppressed` | +| Own membership | `localMember/LocalMember.ts` (`enterRTCSession`), `localMember/HomeserverConnected.ts` | `joinRTCSession`, `leaveRoomSession(1000)`, `updateCallIntent`, `MembershipManagerEvent.*`, `ClientEvent.Sync`; delegation probe at `LocalMember.ts:298-313`, delegation through the JWT service at `:731-756` | +| SFU / JWT | `src/livekit/openIDSFU.ts`, `localMember/LocalTransport.ts`, `localMember/RtcTransportAutoDiscovery.ts`, `remoteMembers/Connection.ts`, `ConnectionFactory.ts`, `ConnectionManager.ts` | `getOpenIdToken`, `_unstable_getRTCTransports`, `POST /get_token` (+ `delay_id`, `delay_timeout`, `delay_cs_api_url`), legacy `/sfu/get` | +| Remote member ↔ LiveKit identity | `remoteMembers/MatrixLivekitMembers.ts` | `rtcBackendIdentity`, `userId`, `deviceId`, `memberId` | +| E2EE media keys | `src/e2ee/matrixKeyProvider.ts`, `src/e2ee/sharedKeyManagement.ts` | `EncryptionKeyChanged`, `reemitEncryptionKeys`, `room.hasEncryptionStateEvent` | +| Room metadata | `remoteMembers/MatrixMemberMetadata.ts`, `src/utils/displayname.ts`, `src/room/useRoomName.ts`, `useRoomState.ts`, `useRoomAvatar.ts`, `useJoinRule.ts`, `InviteModal.tsx`, `CallView.tsx` | `getMembersWithMembership`, `RoomStateEvent.Members`, `room.name`, `getMxcAvatarUrl`, `getJoinRule`, `getCanonicalAlias` | +| Own profile / avatars | `src/profile/useProfile.ts`, `src/Avatar.tsx` | `getUser`, `UserEvent.*`, `setDisplayName`, `setAvatarUrl`, `uploadContent`, `mxcUrlToHttp`, `getAccessToken` | +| Reactions / hand raise | `src/reactions/ReactionsReader.ts`, `useReactionsSender.tsx`, `src/reactions/index.ts` | `RoomEvent.Timeline/Redaction/LocalEchoUpdated`, `MatrixEventEvent.Decrypted`, `relations.getChildEventsForEvent`, `sendEvent`, `redactEvent`, membership `eventId`, `RelationType` | +| Call notifications | `CallViewModel/CallNotificationLifecycle.ts` | `DidSendCallNotification`, `RoomEvent.Timeline` + `EventType.RTCDecline` | +| Rageshake / dev settings | `src/settings/submit-rageshake.ts`, `rageshake.ts`, `FeedbackSettingsTab.tsx`, `DeveloperSettingsTab.tsx` | `getCrypto`, `sendEvent(org.matrix.rageshake_request)`, `ClientEvent.Event`, `secureRandomString`, `doesServerSupportUnstableFeature`, `getSFUConfigWithOpenID` | +| Analytics | `src/analytics/PosthogEvents.ts`, `PosthogAnalytics.ts` | `rtcSession.statistics`, account data | +| Types only | `src/UrlParams.ts`, `src/state/MediaDevices.ts`, `AndroidControlledAudioOutput.ts`, `IOSControlledAudioOutput.ts`, `initialMuteState.ts`, `state/media/RingingMediaViewModel.ts` (`RTCCallIntent`), `src/useEvents.ts` (`TypedEventEmitter` types) | replaced by a local `CallIntent` type / kept as generic emitter typing | +| Runtime misc | `src/useLocalStorage.ts` (`TypedEventEmitter`), `src/room/GroupCallErrorBoundary.tsx` (`MatrixError`), `src/room/KnockLobbyView.tsx` (shell) | see S6 | +| Context | `src/ClientContext.tsx` | `useClient`/`useClientState` used by `Avatar`, `sharedKeyManagement`, `useReactionsSender`, `submit-rageshake`, `DisconnectedBanner` | + +Hosts: `component/index.tsx:291`, `src/room/useLoadGroupCall.ts:335`, +`sdk/main.ts:128` (own `MatrixRTCSessionManager`; waits on +`MatrixRTCSessionEvent.JoinStateChanged` at `:292`). Test kit: +`src/utils/test.ts` (`MockRTCSession`, `mockRtcMembership`, `mockMatrixRoom`), +`src/utils/test-viewmodel.ts`, `CallViewModelTestUtils.ts`. Baseline on +`main` (fe911628): tsc green, 97 unit files / 757 tests green. + +Component build: `vite-component.config.ts` (single string `fileName`, +externals list with 18 `matrix-js-sdk/lib/*` subpaths), `pnpm lint:externals`, +`component/package.json` (`matrix-js-sdk: "*"` peer, `exports` without a +wildcard). + +--- + +## 3. What the crate gives us, what it does not, and what must change in it + +Verified against `src/uniffi_api/mod.rs`, `src/participation/mod.rs`, +`src/session/state.rs`, `src/own_membership/machine.rs`, +`src/encryption/matrix_encryption_event.rs` and the generated +`web-test-app/src/generated/matrix_rtc.ts` (acceptance suites: 32 pass). + +**Provided** (`FfiParticipationManager`, one per `(room, slot)`, any number +share one `FfiMatrixDriver`): + +- `join(FfiTransportIntent, FfiJoinParams)` / `leave(code?, reason?)`; a + `Publish` intent with a bare LiveKit transport triggers discovery through + `driver.getRtcTransports()` (`connections/mod.rs:470-499`); a driver _error_ + there is `NoTransport`, not a fallback. +- `memberships()` + listener: `FfiMembership { member { memberId, userId, +deviceId, displayName?, avatarUrl?, intent?, applicationType?, +publishedTransports, canSubscribe }, state: Joined | LeftWithKeys, +connections: serviceUrl[] (the FFI doc comment saying ws urls is wrong), +transportIdentity?, mediaKey? }`. `transportIdentity` is today's + `rtcBackendIdentity`. `LeftWithKeys` entries have empty `connections`. +- `connections()` + listener: `{ connection { serviceUrl, wsUrl, jwtToken, +expiresAtTs }, members }[]`; tokens re-minted a minute before `exp`. +- `keyMap()` + `setKeyMapListener(map, change)`: `FfiMediaKey { memberId, key: +ArrayBuffer, index, creationTsMs: bigint }`, inbound keys **and our own** + (`encryption/inbound.rs:251-257`). +- `status()` + listener: `Disconnected{cause} | Joining | Connected{keepAlive, +membership, roster, encryption, impairments} | Leaving`. +- `session()`, `ownMemberId()` (available as soon as `join()` starts), + `ownMembership()`, `connectionProblems()`, `debugSnapshot()`. +- Member display names and avatars, from the room's `m.room.member` state + (C8): the session keeps them current, so a rename is a memberships change. +- Slots are required: once the seed has read slot state, a slot with no event + is closed, so a room without an `m.rtc.slot` has no call, in every dialect. + `openSlot(application, encrypted)` / `closeSlot()` send the state event; + the slot id `m.call#ROOM` matches js-sdk's default. +- `FfiElementCallCompat.{Off, StickyEvents, StateEvents}` today; `StickyEvents` + is removed by C9, leaving `Off` (spec MSC4143) and `StateEvents` (MSC3401). +- All `u64` fields are `bigint` in TypeScript; `Vec` is `ArrayBuffer`. +- Listener callbacks arrive one timer tick after the emitting call (pumps + sleep through `setTimeout`, `executor.rs:86`); getters are fresh. + +**Not provided — Element Call keeps it, through the driver** (§4.1 slices): + +| Need | Why not in the crate | Where it goes | +| ------------------------------------------------------------------------------ | ---------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- | +| Room name, alias, avatar, join rule, encryption flag | room metadata | `RoomDriver.getRoomInfo` | +| Profiles of room members who are not in the call (ringing, name-tag threshold) | not RTC | `RoomDriver.subscribeRoomMembers` | +| Reactions, hand raise, `org.matrix.rageshake_request` | application events | `TimelineDriver` | +| MSC4075 notification + decline | out of scope (only `wire_event_type` knows the type) | `TimelineDriver.sendRoomEvent`, decided in `CallNotificationLifecycle` (§4.3) | +| Own profile read/write | not RTC | `ProfileDriver` | +| `mxc://` thumbnails with auth | not RTC | `MediaDriver.thumbnailUrl` | +| Homeserver sync connectivity | needed by the crate too | `RtcMatrixDriver` (`isHomeserverConnected`, `subscribeConnectivity`, C12); reaches Element Call as `HomeserverUnreachable` in the status | +| Sticky-events support probe | capability probe | `MatrixDriver.getCapabilities()` | + +**Must change in the crate (S0a) — each blocks a later slice:** + +| # | Problem | Change | +| --- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| C1 | A successful `read_state("m.rtc.slot")` returning `[]` marks slot state supplied and every slot other than the legacy `""` resolves `Closed` (`session/state.rs`); `join()` then fails with `SlotClosed` and every MSC4143 peer is excluded. Element Call never sent `m.rtc.slot`. | **Kept as the crate has it: no slot means no call.** Element Call opens the slot when nobody has (`CallParticipation.join` with a `SlotPolicy`: `openSlot("m.call", encrypted)`, then wait for the echo), which needs the power level to send `org.matrix.msc4143.rtc.slot`; without it the join fails with `NoOpenSlotError`. Existing rooms keep working because the first call in a room opens its slot. A compat-mode relaxation was tried and reverted. | +| C2 | `manage_media_keys`, `require_cross_signed_sender`, `use_key_delay_ms` are not settable over the FFI; defaults are `true`, `true`, 1000 ms. | New record `FfiParticipationConfig { compat, manage_media_keys, require_cross_signed_sender, use_key_delay_ms }` as the constructor argument (replaces the bare `compat`). | +| C3 | `StickyEvents` compat sent keys as `org.matrix.msc4143.rtc.encryption_key` while deployed clients read only `io.element.call.encryption_keys`. | Made moot by C9 and reverted with it: the sticky dialect goes away entirely, so `Off` sends the spec key message and `StateEvents` the legacy one, with no middle case. | +| C4 | `FfiMember` has no membership `event_id`; reactions relate to it (§4.3). | `Member.event_id: Option` threaded through `session/dispatch.rs` → `convert/*` → `state.rs` (currently dropped at `state.rs:402`) → `FfiMember.event_id`. | +| C5 | Delegating the delayed leave (MSC4195) is split between the crate and the host: the draft's driver method makes the _adapter_ perform the whole delegation, its demo adapter calls a homeserver endpoint that 401s on a widget client, and Element Call today does it differently (probe, then the authorisation service's `get_token` with `delay_id`/`delay_timeout`/`delay_cs_api_url`). Nothing of this exists in the real `crates/` yet. | **The crate owns the policy; the driver keeps two primitives.** (a) `delegate_delayed_leave_via_homeserver(room, slot, member, delay_id)`: one authenticated POST to the CS API endpoint (`/_matrix/client/unstable/io.element.msc4195/rtc/livekit/delegate_delayed_leave`, the spelling Element Call probes today; a widget client answers `Unsupported`). (b) `LivekitTokenRequest.delegation: Option<{ delay_id, delay_timeout_ms }>`: the adapter appends `delay_id`, `delay_timeout` and `delay_cs_api_url` (its own homeserver URL) to the `get_token` / `sfu/get` body it already sends. The own-membership machine tries (a) first and, on `Unsupported` or any failure, (b) against the transport we publish on, i.e. Element Call's OpenID → JWT → scheduled-event path; only if both fail does it keep restarting the switch itself. **Arm-after-confirm:** the short delayed leave stays armed through the join; delegation arms a second, ≥ 1 h delayed leave, delegates _that_, and cancels the short one on success (or the long one on failure), so no moment is left without an armed leave and a failed delegation costs nothing. `KeepAlive::Delegated` says which route succeeded. The interim C5 (service URL and delay on the request) and Element Call's driver-side probe and JWT delegation are replaced by this. | +| C6 | The transport identity is a pure function (`connections/mod.rs:116-135`) but not exported; the own identity is needed before our membership echo to set our own media key. | Export `FfiParticipationManager.own_transport_identity(): Option`. | +| C7 | Doc comment on `FfiMembership.connections` says `ws_url`s. | Fix the comment. | +| C8 | Both converters set `display_name` / `avatar_url` to `None`, so every host would re-derive them from room members. | The session records each `m.room.member` profile (whether or not the roster condition is enforced) and stamps it on members at projection time. | +| C9 | `ElementCallCompat::StickyEvents` models the 2025 Element Call sticky dialect (`member: {user_id, device_id, id}`, flat `rtc_transports`, `versions`, legacy key message). No deployment uses it: sticky-event calls have not shipped. | **Remove the mode.** Delete `own_membership/compat_2025.rs`, the 2025 block in `session/convert/msc4143.rs` and its dispatch arm, the `StickyEvents` variants of `ElementCallCompat` / `FfiElementCallCompat`, and their tests and acceptance tests; `outbound_event_type` / `build_content` keep two arms (`Off`, `StateEvents`). Element Call then maps `Matrix_2_0 → Off`: spec MSC4143 sticky events with slots (which Element Call opens, C1) and the spec key message. | +| C10 | `MediaKeyState` has `holds_our_key`, `have_their_key` and `rejection`, so a tile learns about an unsigned sender only when `require_cross_signed_sender` is on (the key is discarded, `rejection: NotCrossSigned`). With the check off the verdict is dropped on accept and the tile cannot show an unverified sender. | Keep the MSC4153 verdict of the accepted key per member and expose it as `FfiMediaKeyState.sender_cross_signed: Option` (`None` when the host could not tell). Element Call runs with the check off (§5.8) and wants to show the state on the tile until it is turned on. | +| C11 | No way to change `application["m.call.intent"]` while joined; Element Call flips it between `audio` and `video` when the camera is toggled (`updateCallIntent`). | `update_application(intent)` on the own-membership manager, facade and FFI: while connected the membership is re-published at once on the refresh path (a failure retries like a refresh); during a join the join event carries it; refused with `NotJoined` otherwise. | +| C12 | Homeserver connectivity lived only in Element Call's driver; the crate could not tell a dead homeserver from a quiet one, and a participation's status said nothing about it. | **Done.** `ConnectivityDriver` (`is_homeserver_connected`, `subscribe_connectivity`) joins the `MatrixDriver` sum; the FFI adds `ConnectivitySink`, the two callback methods and `FfiParticipationManager.is_homeserver_connected()`; the facade pump consumes the stream and reports `Impairment::HomeserverUnreachable { since_ts }` (Critical, sorted first) in every non-disconnected status until the driver reports the homeserver back. The web-test-app mock and js-sdk driver implement it. A matrix-rust-sdk adapter implements the same two methods later. | + +No crate work is deferred: `update_application` is C11. + +--- + +## 4. Target architecture + +```text +host (SPA · widget · sdk · a third-party page) + ├─ RtcMatrixDriver = the crate's MatrixDriverCallback, verbatim + │ (events, to-device, tokens, sinks, connectivity) + └─ ElementCallMatrixClientDriver = RoomDriver + TimelineDriver + ProfileDriver + + MediaDriver + capabilities + │ + ▼ component/index.tsx + ┌─ MatrixDriverProvider (src/driver/MatrixDriverContext.tsx) ─────────────┐ + │ CallView owns one CallParticipation for lobby → call → ended │ + │ CallParticipation (src/state/rtc/CallParticipation.ts) │ + │ FfiMatrixDriver(driver) → FfiParticipationManager(room, slot, me, cfg)│ + │ memberships$ · connections$ · keyChanges$ · status$ · session$ │ + │ ownMemberId$ · ownMembership$ · ownTransportIdentity$ │ + │ join(intent, params) · leave(reason) │ + │ │ │ + │ ▼ │ + │ createCallViewModel$(scope, callParticipation, roomInfo, mediaDevices, …) │ + │ ConnectionManager ← connections$ (wsUrl + jwt; no OpenID in EC) │ + │ RemoteMembers ← memberships$ (transportIdentity ↔ LK participant)│ + │ MatrixKeyProvider ← keyChanges$ (memberId → transportIdentity) │ + │ LocalMember ← status$, ownMembership; join/leave → participation│ + │ MemberMetadata ← driver.room members │ + │ Notifications ← driver.timeline + memberships$ │ + │ React: Lobby / InCall / Settings / Avatar / Reactions │ + │ read the driver via useMatrixDriver(), never a client │ + └──────────────────────────────────────────────────────────────────────────┘ +``` + +### 4.1 The two drivers (host-facing, framework-neutral) + +Two files, two objects. `src/driver/RtcMatrixDriver.ts` is one line: the +crate's `MatrixDriverCallback`, re-exported. Everything MatrixRTC, including +homeserver connectivity (C12), goes through it and is consumed by the crate. +`src/driver/ElementCallMatrixClientDriver.ts` is what a call needs beyond +MatrixRTC. Plain TypeScript: async methods and +`subscribeX(listener) → unsubscribe` pairs, mirroring the crate's sink style. +No RxJS crosses this boundary; Element Call wraps subscriptions into +`Behavior`s internally (`src/driver/observe.ts`). + +```ts +export interface ElementCallMatrixClientDriver + extends RoomDriver, TimelineDriver, ProfileDriver, MediaDriver { + readonly userId: string; + readonly deviceId: string; + /** The room this driver is bound to (one driver per room, as in the crate). */ + readonly roomId: string; + getCapabilities(): Promise; + /** Free-form diagnostics for rageshakes (crypto version, sync state, …). */ + getDiagnostics?(): Promise>; +} +export interface DriverCapabilities { + stickyEvents: boolean; + /** The host's events carry decryption metadata (false on a widget client). */ + verifiedEventOrigins: boolean; + /** The host can evaluate MSC4153 cross-signing of senders. */ + crossSigningVerdicts: boolean; +} + +// src/driver/RtcMatrixDriver.ts +export type RtcMatrixDriver = MatrixDriverCallback; + +export interface RoomInfo { + name: string; + canonicalAlias: string | null; + avatarUrl: string | null; + joinRule: string | null; + encrypted: boolean; +} +export interface RoomMemberProfile { + userId: string; + displayName: string | null; + avatarUrl: string | null; + membership: "join" | "invite"; +} +export interface RoomDriver { + getRoomInfo(): RoomInfo; + subscribeRoomInfo(listener: (info: RoomInfo) => void): () => void; + getRoomMembers(): RoomMemberProfile[]; + subscribeRoomMembers( + listener: (members: RoomMemberProfile[]) => void, + ): () => void; +} + +export interface TimelineEvent { + eventId: string; + type: string; + sender: string; + content: Record; + originServerTs: number; + redacts?: string; +} +export interface TimelineDriver { + sendRoomEvent( + eventType: string, + content: unknown, + ): Promise<{ eventId: string }>; + redactEvent(eventId: string): Promise; + /** Decrypted live room events (not sticky), incl. redactions; no local echoes. */ + subscribeTimeline(listener: (event: TimelineEvent) => void): () => void; + /** Events already known that relate to `eventId` (hand-raise catch-up). */ + getRelatedEvents( + eventId: string, + relType: string, + eventType: string, + ): TimelineEvent[]; +} + +export interface OwnProfile { + displayName: string | null; + avatarUrl: string | null; +} +export interface ProfileDriver { + getOwnProfile(): OwnProfile; + subscribeOwnProfile(listener: (profile: OwnProfile) => void): () => void; + /** Absent when the host does not allow profile changes. */ + setDisplayName?(name: string): Promise; + setAvatar?(file: Blob): Promise; +} + +export interface MediaDriver { + /** An ``-usable URL for an mxc thumbnail (may be a blob: URL), or null. */ + thumbnailUrl( + mxcUrl: string, + width: number, + height: number, + resizeMethod: "crop" | "scale", + ): Promise; +} +``` + +The client driver is a union of capability slices, the way the crate splits +its own driver; the RTC driver is the crate's contract untouched, so a host +with a crate-side adapter (matrix-rust-sdk) implements nothing extra for +MatrixRTC. + +### 4.2 `CallParticipation` (Element Call's RxJS view of the manager) + +Naming: _participation_ is the crate's FFI concept (`FfiParticipationManager`, +`FfiParticipationConfig`); `CallParticipation` is Element Call's RxJS wrapper +over it. + +`src/state/rtc/CallParticipation.ts`, a class taking the scope in its constructor: + +```ts +new CallParticipation(scope, driver, { + slotId: "m.call#ROOM", compat, manageMediaKeys, requireCrossSignedSender, + useKeyDelayMs, transportFallbackUrl?, logger }) + memberships$: Behavior> // Joined only; LeftWithKeys filtered (v1) + connections$: Behavior + keyChanges$: Observable // one changed key per emission + keyMap$: Behavior + status$: Behavior + session$: Behavior + ownMemberId$: Behavior + ownTransportIdentity$: Behavior + ownMembership$: Behavior + join(intent: FfiTransportIntent, params: FfiJoinParams): Promise + leave(code?: string, reason?: string): Promise +``` + +- Wraps `new FfiMatrixDriver(driver)` and `new FfiParticipationManager(...)`; + `uniffiDestroy()` on scope end (leave first unless `Disconnected`). +- `transportFallbackUrl` decorates `getRtcTransports`: when the host's call + **throws or returns no LiveKit transport**, answer with + `Config.get().livekit.livekit_service_url` (today's precedence, + `RtcTransportAutoDiscovery.ts:72-94`). +- Lives at `CallView` level (the lobby reads memberships for the participant + count, auto-mute threshold and notification decision, `CallView.tsx:164-413`; + `useReactionsSender` needs the own membership). `join()` after `leave()` on + one manager is supported and mints a fresh member id. +- Behaviors are seeded from the getters and updated by the listeners. + +### 4.3 `createCallViewModel$` after the change + +```ts +createCallViewModel$( + scope, + participation, + roomInfo, + mediaDevices, + muteStates, + options, + handsRaised$, + reactions$, + trackProcessorState$, +); +// roomInfo: { roomId, userId, deviceId, members$: Behavior, +// homeserverConnected$: Behavior, timeline: TimelineDriver } +``` + +| Today | After | +| ------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `createMemberships$(scope, rtcSession)` | `callParticipation.memberships$` | +| `membershipsAndTransports$` (`getTransport(oldest)`) | `membership.connections[]` (service urls) | +| `createLocalTransport$` + `RtcTransportAutoDiscovery` + `openIDSFU` | deleted; `join(Publish(custom url or bare))`; own transport = `ownMembership.member.publishedTransports[0]` | +| `Connection.start()` fetching a JWT | `Connection` takes `{ wsUrl, jwt, expiresAtTs }` from `connections$`, keyed by `serviceUrl`, holds `token$`; a refreshed token is used on the next full (re)connect; `expiresAtTs` logged on connect; `livekitAlias` decoded from the JWT stays | +| `createRemoteMatrixLivekitMembers$` on `rtcBackendIdentity` | matches `membership.transportIdentity`; key = `member.memberId` | +| `MatrixKeyProvider.setRTCSession` | `MatrixKeyProvider.attach(participation)`: `keyChanges$` × `memberships$` × `ownTransportIdentity$` → `onSetEncryptionKey(material, identity, index)`; keys whose member has no identity yet are held per member id and replayed | +| `enterRTCSession` (`joinRTCSession(...)`) | `callParticipation.join(intent, joinParamsFromConfig(...), { encrypted: roomInfo.encrypted, canOpen: roomInfo.canOpenSlot })` in the same `scope.reconcile`: opens the room's slot first when none is open (power level permitting, otherwise `NoOpenSlotError`), then joins; cleanup calls `callParticipation.leave()` | +| `createHomeserverConnected$` | `status$` alone: `Impairment::HomeserverUnreachable` (C12) = disconnected; `Connected` with `keepAlive` `Armed`/`Delegated`/`Unavailable` = connected; `RestartFailing`/`Expired` = reconnecting (**behaviour change**: local media pauses in that window, today it does not). Outside a participation, `CallParticipation.homeserverConnected$` from the manager's getter | +| `delayId$` + JWT-service delegation | gone from Element Call. `FfiJoinParams.delegateDelayedLeave` is always `true`; the crate tries the CS API, then the authorisation service's token endpoint (with `delay_id`, `delay_timeout`, `delay_cs_api_url`), then falls back to its own restarts (C5). `config.matrix_rtc_session.delegated_delayed_leave.delay_ms` becomes `FfiJoinParams.delegatedDelayMs` (default 1 h) | +| `createMatrixMemberMetadata$(scope, matrixRoom)` | tiles read `member.displayName` / `avatarUrl` from the crate; disambiguation runs over the call's members; `roomInfo.members$` remains only for the ringing name and the name-tag threshold | +| `createSentCallNotification$` / `createReceivedDecline$` | `CallNotificationLifecycle`: after **our own membership echo** (`ownMembership$` non-null) and when no other member was in the session before our join, send `m.rtc.notification` (wire `org.matrix.msc4075.rtc.notification`) via `driver.sendRoomEvent` with the fields js-sdk sends today (`m.mentions`, `notification_type`, `sender_ts`, `lifetime` 90 s, `m.call.intent`, `m.relates_to: m.reference → own membership event id`, `MatrixRTCSession.ts:725-756`); decline from `driver.subscribeTimeline` on both `org.matrix.msc4310.rtc.decline` and `m.rtc.decline` | +| `updateCallIntent` on camera toggle | `callParticipation.updateApplication(videoEnabled ? "video" : "audio")` (C11); Element X's room-header intent keeps following the camera | +| `createKeyRotationSuppressed$` + `key_rotation_participant_limit` | dropped (the crate has no participant limit; the indicator has no equivalent) | +| `rtcSession.statistics` (PostHog) | counts of `keyChanges$` (sent = own member id, received = others) | +| `MembershipManagerError` → `StickyEventsRequiredError` | `status$` `Disconnected{cause: JoinFailed{error: Driver/Unsupported}}` → `StickyEventsRequiredError`; `NoTransport` → `MatrixRTCTransportMissingError`; `ManagerStopped`/`SlotClosed` → `ConnectionLostError` | +| `impairments` | fed into the inert `src/state/ServiceInterruptionsViewModel.ts` (S6) | + +Join parameters (`joinParamsFromConfig`, from `Config.get().matrix_rtc_session`): +`stickyDurationMs = BigInt(Math.min(membership_event_expiry_ms ?? 4 h, 1 h))` +(js-sdk caps sticky at 1 h, the crate clamps to 1 h; the config default is +undefined today); `keepAliveTimeoutMs = BigInt(delayed_leave.delay_ms)`; +`degradedLifetimeMs = undefined`; `applicationType = "m.call"`; +`intent = options.callIntent`. Config keys that stop having an effect and are +documented as such in `docs/`: `delayed_leave.restart_ms`, +`restart_timeout_ms`, `network_error_retry_ms`, +`key_rotation_participant_limit`, `delegated_delayed_leave.*` (the crate arms +1 h when delegating). `wait_for_key_rotation_ms` maps to +`FfiParticipationConfig.useKeyDelayMs`. + +Compat: `MatrixRTCMode.Compatibility → StateEvents`, `Matrix_2_0 → Off` (spec +MSC4143: sticky member events, slots, the spec key message). Until C9 lands the +code still maps `Matrix_2_0` to the crate's `StickyEvents`; `compatForMode` is +the one place that changes. + +### 4.4 React tree + +- `src/driver/MatrixDriverContext.tsx`: `MatrixDriverProvider` holding both + drivers, `useRtcMatrixDriver()` / `useClientDriver()`; replaces every + `useClient()`/`useClientState()` under `CallView`. `ClientContext` stays for the shell. +- `CallView` props: `{ driver, isPasswordlessUser, confineToRoom, preload, skipLobby }`. + It creates the `CallParticipation` (scope tied to its mount) and hands it to + `LobbyView`, `ActiveCall`, `useReactionsSender`. `MatrixInfo` comes from + `driver.getRoomInfo()` / `driver.getOwnProfile()`. +- `InCallView`'s own id becomes `${driver.userId}:${driver.deviceId}`. +- `Avatar` → `driver.thumbnailUrl` (host bridge `downloadMedia` first). +- `useProfile(client)` → `useOwnProfile()`; `ProfileSettingsTab` hides editing + when `setDisplayName` is absent. +- `ReactionsReader(scope, participation, driver)`, `useReactionsSender` over + `TimelineDriver`. Relation target stays the **current own membership event + id** (`member.eventId`, C4) — protocol status quo; the reader keys raised + hands by `memberId` and re-resolves the event id on re-send instead of + dropping the hand. +- `useRoomEncryptionSystem` reads `getRoomInfo().encrypted`. +- `submit-rageshake`: `useMatrixDriver()` for ids and `getDiagnostics?()`; + rageshake requests via `subscribeTimeline`. +- `DeveloperSettingsTab`: sticky probe → `getCapabilities()`; custom LiveKit + URL validation → `driver.getLivekitToken(...)`. +- `DisconnectedBanner` → `HomeserverUnreachable` in `status$` (C12). +- `window.rtcSession` debug handle → `window.matrixRtc = { participation }`. + +### 4.5 Hosts + +- **Component**: `ElementCallProps.rtcDriver: RtcMatrixDriver` and + `clientDriver: ElementCallMatrixClientDriver`; `roomId` stays as an + **optional** prop for one release and must equal `clientDriver.roomId` when given + (assertion), then goes. `initializeElementCall(config, { matrixRtcWasm? })` + awaits `initMatrixRtcSdk()`. Externals shrink to `react*`, `livekit-client`, + `matrix-js-sdk/lib/logger`. `JsSdkRtcMatrixDriver` and `JsSdkElementCallMatrixClientDriver` are + exported from a second entry `@element-hq/element-call-component/matrix-js-sdk` (needs + `lib.fileName` as a function and a new `exports` key); only that entry has + `matrix-js-sdk` as a peer. +- **SPA / widget**: `useLoadGroupCall` returns the `Room`; `RoomPage` memoises + the two js-sdk drivers and renders ``. The + widget capability list in `src/widget.ts` grows by: send and receive state + `m.rtc.slot` and `org.matrix.msc4143.rtc.slot` (opening the slot), `m.room.avatar`, + `m.room.canonical_alias`, `m.room.join_rules`; send/receive to-device + `org.matrix.msc4143.rtc.encryption_key` and `m.rtc.encryption_key` + (alongside `io.element.call.encryption_keys`); events `m.rtc.decline`. +- **`sdk/main.ts`**: builds the driver from the widget client, a + `CallParticipation`, and waits on `status$` instead of `JoinStateChanged`. +- **`component/dev` harness**: the two js-sdk drivers per pane. + +### 4.6 The js-sdk drivers — two classes, two clients each + +`src/driver/jsSdk/JsSdkRtcMatrixDriver.ts` (the crate seam, a port of the +draft's `jsSdkDriver.ts`, connectivity from `ClientEvent.Sync`) and +`JsSdkElementCallMatrixClientDriver.ts` (the §4.1 slices), both written so +that they work on a full `MatrixClient` +**and** on js-sdk's `RoomWidgetClient` (`node_modules/matrix-js-sdk/src/embedded.ts`). +Differences from the draft, all required by the widget client: + +- to-device inbound: listen on `ClientEvent.ToDeviceEvent` (the widget client + never emits `ReceivedToDeviceMessage`, `embedded.ts:788-802`); on a full + client use `ReceivedToDeviceMessage` for the `encryptionInfo`. +- to-device outbound: always `encryptAndSendToDevice` (works without a crypto + backend on the widget client, `embedded.ts:598-612`; plain `sendToDevice` + there is **unencrypted**, `:614-619`). +- transports: `client._unstable_getRTCTransports()` (the widget override, + `embedded.ts:641-646`), never a raw `http.authedRequest`; `.well-known` + fallback only on a full client. +- event origins: on a full client from decryption metadata (as the draft); on + a widget client events arrive decrypted without metadata, so the driver + reports `Encrypted{ senderDeviceId: content.member.device_id }` for member + events and `Encrypted{ senderDeviceId: content.device_id }` for key + events, i.e. the _claimed_ trust level js-sdk applies today + (`ToDeviceKeyTransport.ts:133-140`). `getCapabilities().verifiedEventOrigins` + says which. +- cross-signing verdict: `undefined` on a widget client + (`crossSigningVerdicts: false`); Element Call then forces + `requireCrossSignedSender = false`. +- delegation: two primitives and no policy. `delegateDelayedLeaveViaHomeserver` + is one `authedRequest` on a full client and `Unsupported` on a widget + client; `getLivekitToken` appends `delay_id`, `delay_timeout` and + `delay_cs_api_url` (`client.baseUrl`) when the request carries a + delegation. The crate decides when to call which (C5). Until C5 lands the + driver still carries Element Call's probe and JWT delegation; both go then. +- sticky listener attached after `startClient()` resolves (the widget room + only exists then, `embedded.ts:326`). +- `getLivekitToken` reuses today's request shapes (`slot_id: "m.call#ROOM"`, + legacy `/sfu/get`), errors mapped to `RtcError` incl. `M_LIMIT_EXCEEDED → +RateLimited`, 403 → `Rejected`, 404/`M_UNRECOGNIZED` → `Unsupported`. + +--- + +## 5. Decisions and assumptions + +1. **Vendored bindings.** `src/matrix-rtc-sdk/generated/` holds `matrix_rtc.ts`, + `matrix_rtc-ffi.ts`, `wasm-bindgen/index.js`, `index_bg.wasm` and a + hand-written `wasm-bindgen/index.d.ts` (no `allowJs` in `tsconfig.json`), + synced by `scripts/sync-matrix-rtc-sdk.sh` (runs `ubrn build web` in the + draft **without** the `runtime-probe` feature, copies). Committed so CI + works. `@ubjs/core` becomes a dependency. The wasm is ~6.5 MB unoptimised. + **Assumption:** committing the binary is acceptable for the draft phase. +2. **Wasm loading.** Verified: Vite 8 library mode inlines `?url` and + `new URL(…, import.meta.url)` assets as base64 regardless of + `assetsInlineLimit`; `?url&no-inline` emits a file. App builds use `?url`; + the component build uses `?url&no-inline` plus an `exports` entry for + `./dist/assets/*`, and `initializeElementCall(config, { matrixRtcWasm })` + lets a host point elsewhere. vitest reads the file from disk; wasm boot is + **lazy** (only suites that need it call `initMatrixRtcSdk()`), never in + `src/vitest.setup.ts`; Storybook boots it in `.storybook/preview.tsx` + `beforeAll`. Suites using `vi.useFakeTimers` never share a file with + real-wasm tests (pumps sleep on `setTimeout`). +3. **Own identity via the driver.** `userId`/`deviceId` are properties of the + driver, not props. +4. **One driver per room**, as in the crate. +5. **`matrix-js-sdk/lib/logger` stays** behind `src/utils/logger.ts`. +6. **`updateCallIntent` stays**, through the crate's `update_application` (C11). +7. **Reactions relate to the current own membership event id** (status quo); + reader keys by `memberId`. Alternatives (stable join event id, or + `memberId` as relation target) are protocol changes left to the user. +8. **MSC4153 default off** (`requireCrossSignedSender = false`) for every + host, confirmed: js-sdk performs no such check today, and a passwordless + SPA peer would otherwise be inaudible to everyone. The intent is to turn + it on; the default carries a TODO (`src/state/rtc/joinParams.ts`), and C10 + puts the sender's verdict on the tile so the UI can show it meanwhile. +9. **Delegation is the crate's alone.** Element Call always asks for it; the + crate tries the CS API, then the authorisation service's token endpoint, + then its own restarts, and arms the long delegated leave only once + delegation is confirmed (C5). Element Call keeps no probe and no + delegation code. +10. **Widget trust model:** origins synthesised from claimed device ids equal + today's js-sdk trust level; the crate records them as + `DeviceAttribution::Verified` because it cannot tell. Documented in the + driver; a `Claimed` attribution flag on the sink is a follow-up crate ask. +11. **Scratch files** go to `agent-workspace/oxidation/`; this plan lives at + the repo root because it was asked for by name. +12. **Branch** `toger5/oxidation`, one commit per slice. + +--- + +## 6. Work breakdown + +Each slice is independently green (`pnpm lint && pnpm test:unit` at least). + +### S0a — crate changes ☑ (in `MatrixSdkArchitectureDraft`) + +C2–C12 from §3 (C1 reverted), each with a Rust unit test; acceptance tests in +`web-test-app/test/`: a slot-less room refuses joins until `openSlot`, in every dialect; +`FfiParticipationConfig` with `manageMediaKeys: false` exchanges no keys; +no `StickyEvents` variant left anywhere (C9); `member.eventId` present; +delegation tries the homeserver first, then the token endpoint with the delay fields, and keeps the short leave armed until one succeeds; +`ownTransportIdentity()` equals the joined membership's `transportIdentity`. +Gate: `cargo test --features uniffi`, `cargo clippy --all-targets --features uniffi -- -D warnings`, +`npm run ubrn:web && npm test`. + +### S0b — SDK intake ☑ + +- `scripts/sync-matrix-rtc-sdk.sh`, `src/matrix-rtc-sdk/generated/**`, + `src/matrix-rtc-sdk/index.ts` (loader + curated re-exports), + `src/matrix-rtc-sdk/index.test.ts` (boot, one join round-trip against the + TS mock driver). +- `package.json` (`@ubjs/core`), `knip.ts` (`ignore` for `generated/**`), + `.oxlintrc.json` `ignorePatterns`, `.oxfmtrc.json` ignore, + `vite.config.ts` (nothing needed for `?url`; verified `vite-plugin-wasm` + ignores it), `tsconfig.json` untouched thanks to the `.d.ts`. +- Gate: `pnpm lint && pnpm format:check && pnpm test:unit`. + +### S1a — driver interface, mock driver ☑ + +- `src/driver/RtcMatrixDriver.ts`, `src/driver/ElementCallMatrixClientDriver.ts`, + `src/driver/observe.ts`, `MockRtcMatrixDriver.ts` (port of + `web-test-app/src/mockDriver.ts`) and `MockElementCallMatrixClientDriver.ts` + (in-memory room info, members, timeline, profile), with a test each. +- `knip.ts` `ignore` for `src/driver/**` until consumed, with the reason. + +### S1b — `JsSdkMatrixDriver` ☑ + +- `src/driver/jsSdk/JsSdkRtcMatrixDriver.ts` and + `JsSdkElementCallMatrixClientDriver.ts` (§4.6) + tests against **two** + fakes: a `MatrixClient`-shaped one (`mockMatrixRoom`) and a + `RoomWidgetClient`-shaped one (`ToDeviceEvent`, no crypto, + `_unstable_getRTCTransports`, sticky updates after `startClient`). + Asserts request shapes of `_unstable_sendStickyEvent`, + `_unstable_sendStickyDelayedEvent`, `_unstable_updateDelayedEvent`, + `encryptAndSendToDevice`, `/get_token` body with and without the delegation fields, `delegateDelayedLeaveViaHomeserver` on both clients, + sink emission and origin synthesis, room-info/member updates. + +### S2 — `CallParticipation` ☑ + +- `src/state/rtc/CallParticipation.ts`, `joinParams.ts`, `transportIntent.ts`, + `errors.ts` (cause → `ElementCallError`). +- `CallParticipation.test.ts` through the real wasm + `MockMatrixDriver`: + memberships follow a remote join/leave; `LeftWithKeys` filtered; join → + `Connected`; `connections$` carries the token; `keyChanges$` fires for a + peer key; `ownTransportIdentity$` set before the echo; leave → + `Disconnected{LeftByHost}`; join → leave → join; scope end destroys the + manager; fallback transport when the host throws or advertises none. + +### S3 — view model, four slices ☐ + +- **S3a** `Connection`/`ConnectionManager`/`ConnectionFactory` keyed by + `serviceUrl`, fed by `Behavior<{ serviceUrl, wsUrl, jwt, expiresAtTs }[]>`, + with a temporary adapter from today's `SFUConfig` so `openIDSFU` stays + until S3c. Introduces `mockCallParticipation()` and `mockFfiMembership()` in + `src/utils/test.ts`. +- **S3b** `MatrixLivekitMembers` + `MatrixKeyProvider` on `FfiMembership` / + key changes, with an adapter from `CallMembership` for the still-js-sdk + `memberships$`. +- **S3c** `LocalMember` on `callParticipation.join/leave` + status-derived + connectivity; delete `LocalTransport.ts`, `RtcTransportAutoDiscovery.ts`, + `HomeserverConnected.ts`, `openIDSFU.ts`, `enterRTCSession`. +- **S3d** `createCallViewModel$` signature, `CallNotificationLifecycle`, + `MatrixMemberMetadata`, `SessionBehaviors.ts` and + `useMatrixRTCSessionMemberships.ts` deleted, `ReactionsReader` on + `participation` + `TimelineDriver`; test kit swapped + (`MockRTCSession`/`mockRtcMembership` deleted). To stay green before S5, + `CallView` builds a `JsSdkMatrixDriver` from its existing `client` / + `rtcSession.room` props as a temporary shim. + +### S4 — React tree, two slices ☐ + +- **S4a** views/hooks/settings on the driver: `CallView.tsx` (owns + `CallParticipation`), `InCallView.tsx`, `LobbyView.tsx`, `CallEndedView.tsx`, + `VideoPreview.tsx`, `useRoomInfo()` (replaces `useRoomName/Avatar/JoinRule/State`), + `InviteModal.tsx`, `Avatar.tsx`, `useOwnProfile.ts`, `ProfileSettingsTab.tsx`, + `SettingsModal.tsx`, `DeveloperSettingsTab.tsx`, `submit-rageshake.ts`, + `DisconnectedBanner.tsx`, `analytics/PosthogEvents.ts`, `controls.ts`, and a + first `CallView.stories.tsx` (lobby, in call, ended) driven by + `MockMatrixDriver`. +- **S4b** reactions and notifications: `useReactionsSender.tsx`, + `ReactionsReader` keyed by `memberId`, `CallNotificationLifecycle` sending + through the driver; tests incl. a membership re-send mid-call. + +### S5 — hosts ☐ + +- `component/index.tsx`, `component/matrix-js-sdk.ts`, `component/package.json` + (`exports`, peers), `vite-component.config.ts` (two entries, `fileName` + function, externals shrink, `?url&no-inline`), `component/tsconfig.build.json`, + `component/dev/Harness.tsx`, `README.md`. +- `src/room/useLoadGroupCall.ts`, `RoomPage.tsx`, `src/widget.ts` + (capabilities, §4.5), `sdk/main.ts`, `playwright/spa-helpers.ts` + (delegation route helper), `docs/` config notes. +- Gate: all four builds; Playwright standalone + widget + component against + `pnpm backend`; a widget media-key round trip and `reconnect.spec.ts` + re-checked under the new delegation path. + +### S6 — fence and cleanup ☐ + +- `src/utils/logger.ts`; local `CallIntent` type for the six `RTCCallIntent` + users; `useLocalStorage.ts` on a local emitter; oxlint + `no-restricted-imports` scoped to the call tree (allow-list: `src/home`, + `src/auth`, `src/utils/spa.ts`, `src/utils/matrix.ts`, `src/driver/jsSdk/**`, + `src/ClientContext.tsx`, `src/widget.ts`, `src/initializer.tsx`, + `src/IndexedDBWorker.ts`, `src/room/KnockLobbyView.tsx`, `src/settings/rageshake.ts`) + banning `matrix-js-sdk` except `matrix-js-sdk/lib/logger`. +- `ServiceInterruptionsViewModel` fed from `status$.impairments`. +- `docs/agents/architecture.md`, `docs/matrix_rtc_modes.md` updated; + `src/@types/matrix-js-sdk.d.ts` removed if nothing merges into js-sdk types. + +--- + +## 7. Risks and mitigations + +| Risk | Mitigation | +| ------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------ | +| A user without the power level to open a slot, in a room that never had a call | `NoOpenSlotError` names the remedy; a room admin opens the slot by starting the first call | +| A client on the removed sticky dialect (none is deployed) | Not supported: `Off` and `StateEvents` are the only dialects (C9) | +| Component bundle size / wasm delivery | `?url&no-inline` + `exports` wildcard + `matrixRtcWasm` override; verified in S0b and S5 | +| Token refresh vs LiveKit reconnect | `Connection.token$`; full reconnect uses the latest token; `expiresAtTs` logged | +| Own identity before the echo | C6 export; JWT `sub` only as a logged cross-check | +| Keys before identity | key provider buffers per member id and replays | +| Widget mode regressions (origins, to-device event, capabilities) | S1b tests against a `RoomWidgetClient` fake; S5 widget e2e adds a media-key round trip | +| Delegation fails after the long leave was armed | Arm-after-confirm (C5): the short leave stays armed until delegation is confirmed | +| Behaviour drift in keep-alive (6 s vs 4 s restarts) and dropped config keys | documented in `docs/` | +| Test time: wasm per file | lazy boot in the suites that need it only | + +--- + +## 8. Verification matrix + +| Check | S0a | S0b | S1 | S2 | S3 | S4 | S5 | S6 | +| ---------------------------------------------------------------------------- | --- | --- | --- | --- | --- | --- | --- | --- | +| `cargo test/clippy`, `web-test-app` suites | ● | | | | | | | | +| `pnpm lint` + `format:check` | | ● | ● | ● | ● | ● | ● | ● | +| `pnpm test:unit` | | ● | ● | ● | ● | ● | ● | ● | +| `pnpm test:storybook` | | | | | | ● | ● | ● | +| four builds | | ● | | | | | ● | ● | +| Playwright standalone + widget + component | | | | | | | ● | ● | +| Manual: two harness panes hear each other, E2EE, hand raise, reaction, leave | | | | | | | ● | | + +--- + +## 9. Open questions for the user (answered by the assumptions in §5 until told otherwise) + +1. Slot semantics, **answered**: no slot means no call; Element Call opens the + slot on the first call in a room, power level permitting. +2. Delegation, **answered**: CS API endpoint first, then Element Call's + OpenID → JWT → scheduled-event path, all inside the crate and invisible to + Element Call (C5). +3. Media-key type under the sticky compat, **answered**: there are no deployed + sticky-event clients, so the compat mode is removed (C9) and the question + with it. +4. MSC4153, **answered**: off everywhere for now, with a TODO to turn it on + and C10 so tiles show unverified senders in the meantime. +5. Reactions relation target: current membership event id (taken), stable join + event id, or `memberId`? +6. Committing the 6.5 MB wasm (taken) vs a build-time fetch. +7. `roomId` prop: optional for one release (taken) vs removed outright. +8. `updateCallIntent`, **answered**: added to the crate as `update_application` + (C11); Element Call keeps the behaviour. + +--- + +## 10. Review log + +Independent review findings incorporated in this revision: slot enforcement +blocker (C1); delegation protocol and 1 h arm (C5, §5.9; later redefined as crate-only with arm-after-confirm); `StickyEvents` key +type interop (C3, then made moot by removing the mode, C9); MSC4153 default (§5.8); widget-client differences for the +js-sdk drivers (§4.6) and missing widget capabilities (§4.5); own identity +export (C6); `CallParticipation` lifetime at `CallView` (§4.2); notification +timing and content (§4.3); reactions/event-id semantics (§5.7); config mapping +defaults and dropped keys (§4.3); `bigint`/`ArrayBuffer` types; inventory +gaps (§2); knip `ignore` vs `ignoreFiles`, oxlint/oxfmt ignores, `.d.ts` for +the glue, lazy wasm boot, Storybook `beforeAll`; slice re-cut (S0a/b, S1a/b, +S3a–d, S4a/b, temporary `CallView` shim); `sdk/main.ts` status wiring and the +Playwright delegation helper. diff --git a/knip.ts b/knip.ts index d9de80c8c..200dbb426 100644 --- a/knip.ts +++ b/knip.ts @@ -26,6 +26,15 @@ export default { // This is a shell built-in. "printf", ], + // uniffi-generated bindings (scripts/sync-matrix-rtc-sdk.sh): every + // export the crate has, most of them unused here by design + ignore: [ + "src/matrix-rtc-sdk/generated/**", + // The host-facing driver seam, landed ahead of its consumers (the + // `CallParticipation` layer and the hosts, see element-call-oxidation-plan.md) + "src/driver/**", + "src/state/rtc/**", + ], ignoreFiles: [ "scripts/.pnpmfile.cjs", // Deliberately added prior to any component or business logic diff --git a/locales/en/app.json b/locales/en/app.json index f3d568bb8..7b1775be5 100644 --- a/locales/en/app.json +++ b/locales/en/app.json @@ -110,6 +110,8 @@ "membership_manager": "Membership Manager Error", "membership_manager_description": "The Membership Manager had to shut down. This is caused by many consecutive failed network requests.", "no_matrix_2_authorization_service": "The authorization service for your media server (SFU) is out of date.", + "no_open_slot": "No call to join here", + "no_open_slot_description": "Nobody has started a call in this room yet, and you do not have permission to start one. Ask a room admin to start the call, or to allow you to start calls.", "open_elsewhere": "Opened in another tab", "open_elsewhere_description": "{{brand}} has been opened in another tab. If that doesn't sound right, try reloading the page.", "peer_connection_timeout": "Connection timeout", diff --git a/package.json b/package.json index 90e5e0394..7bfe8dc1c 100644 --- a/package.json +++ b/package.json @@ -82,6 +82,7 @@ "@types/react-dom": "^19.0.0", "@types/sdp-transform": "^2.4.5", "@typescript-eslint/utils": "^8.61.0", + "@ubjs/core": "0.31.0-5", "@use-gesture/react": "^10.2.11", "@vector-im/compound-design-tokens": "^10.0.0", "@vector-im/compound-web": "^10.0.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2d81f4fa4..e80c0a9ec 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -127,6 +127,9 @@ importers: '@typescript-eslint/utils': specifier: ^8.61.0 version: 8.69.0(eslint@8.57.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3) + '@ubjs/core': + specifier: 0.31.0-5 + version: 0.31.0-5 '@use-gesture/react': specifier: ^10.2.11 version: 10.3.1(react@19.2.8) @@ -3218,6 +3221,9 @@ packages: resolution: {integrity: sha512-+rmdgPA+EXkNgKYvHvFfhrs35utXbwaC5PGpDquSXcoXQDKUA5UjV0LmTucG/4JXkM31BTu4TilHtrN8IVBe8w==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@ubjs/core@0.31.0-5': + resolution: {integrity: sha512-oRBRtyYOhaodiOY3rLMZFgAHGFMmD44XefMpsAx4Ja0/rO+45kVdQB1VZsblQMLYxP965i3IHm56eymgo3I5eQ==} + '@ungap/structured-clone@1.3.3': resolution: {integrity: sha512-60YRaenCQcVjYEKOcG824+DRGGIQ3VKErcBoAEDJZz5bKIs2ZG+X/H9Nk+Q6EVkwJk5QNApxbrc5QtBSwtrXAg==} @@ -8686,6 +8692,8 @@ snapshots: '@typescript-eslint/types': 8.69.0 eslint-visitor-keys: 5.0.1 + '@ubjs/core@0.31.0-5': {} + '@ungap/structured-clone@1.3.3': {} '@use-gesture/core@10.3.1': {} diff --git a/scripts/sync-matrix-rtc-sdk.sh b/scripts/sync-matrix-rtc-sdk.sh new file mode 100755 index 000000000..29847f3cf --- /dev/null +++ b/scripts/sync-matrix-rtc-sdk.sh @@ -0,0 +1,52 @@ +#!/usr/bin/env bash +# +# Copyright 2026 Element Creations Ltd. +# +# SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial +# Please see LICENSE in the repository root for full details. +# +# Vendors the matrix-rtc crate's uniffi web bindings into +# src/matrix-rtc-sdk/generated/. Until the crate ships as an npm package this +# is how Element Call picks up a new build of it: build it there, copy the +# generated TypeScript, the wasm-bindgen glue and the wasm here. +# +# scripts/sync-matrix-rtc-sdk.sh [path-to-MatrixSdkArchitectureDraft] [--no-build] +# +# The build uses web-test-app/ubrn.element-call.config.yaml (feature `uniffi` +# only, release profile, its own output directory so the app's test build is +# left alone). Pass --no-build to copy whatever was built last. + +set -euo pipefail + +DRAFT="${1:-../matrix-rust-rtc/MatrixSdkArchitectureDraft}" +BUILD=1 +for arg in "$@"; do + [[ "$arg" == "--no-build" ]] && BUILD=0 +done + +APP="$DRAFT/web-test-app" +GENERATED="$APP/src/generated-element-call" +DEST="$(cd "$(dirname "$0")/.." && pwd)/src/matrix-rtc-sdk/generated" + +if [[ ! -f "$APP/ubrn.element-call.config.yaml" ]]; then + echo "No web-test-app/ubrn.element-call.config.yaml under $DRAFT" >&2 + exit 1 +fi + +if [[ "$BUILD" == 1 ]]; then + (cd "$APP" && npx ubrn build web --config ubrn.element-call.config.yaml --release) +fi + +mkdir -p "$DEST/wasm-bindgen" +cp "$GENERATED/matrix_rtc.ts" "$GENERATED/matrix_rtc-ffi.ts" "$DEST/" +cp "$GENERATED/wasm-bindgen/index.js" "$GENERATED/wasm-bindgen/index_bg.wasm" "$DEST/wasm-bindgen/" + +REV="$(git -C "$DRAFT" rev-parse --short HEAD 2>/dev/null || echo unknown)" +DIRTY="$(git -C "$DRAFT" status --porcelain 2>/dev/null | grep -q . && echo '-dirty' || true)" +cat > "$DEST/VERSION" < void; + +export interface DriverCapabilities { + /** The homeserver accepts sticky events (MSC4354). */ + stickyEvents: boolean; + /** + * The events the RTC driver emits carry real decryption metadata. A + * widget client receives events already decrypted by its host and can + * only report the device the content *claims*. + */ + verifiedEventOrigins: boolean; + /** The RTC driver can say whether a sending device is cross-signed (MSC4153). */ + crossSigningVerdicts: boolean; +} + +export interface RoomInfo { + name: string; + canonicalAlias: string | null; + /** An `mxc://` URL. */ + avatarUrl: string | null; + /** The `m.room.join_rules` value, `null` while unknown. */ + joinRule: string | null; + /** Whether the room has an `m.room.encryption` state event. */ + encrypted: boolean; + /** + * Whether this user may send the MatrixRTC slot state event + * (`org.matrix.msc4143.rtc.slot`). A call needs an open slot; the client + * that starts a call opens one, which takes the power level for it. + */ + canOpenSlot: boolean; +} + +export interface RoomMemberProfile { + userId: string; + displayName: string | null; + /** An `mxc://` URL. */ + avatarUrl: string | null; + membership: "join" | "invite"; +} + +/** + * Room metadata and the profiles of the people in it. + * + * Call members' names and avatars do not come from here: the crate reads + * `m.room.member` itself and puts them on each membership. This roster is + * for the people who are in the room but not (yet) in the call — the person + * being rung, and how many others there are. + */ +export interface RoomDriver { + getRoomInfo(): RoomInfo; + subscribeRoomInfo(listener: (info: RoomInfo) => void): Unsubscribe; + /** Joined and invited members of the room, in or out of the call. */ + getRoomMembers(): RoomMemberProfile[]; + subscribeRoomMembers( + listener: (members: RoomMemberProfile[]) => void, + ): Unsubscribe; +} + +/** A decrypted room event, as far as a call needs to know it. */ +export interface TimelineEvent { + eventId: string; + type: string; + sender: string; + content: Record; + originServerTs: number; + /** Set on an `m.room.redaction`. */ + redacts?: string; +} + +/** Application events in the room: reactions, hand raises, notifications. */ +export interface TimelineDriver { + sendRoomEvent( + eventType: string, + content: Record, + ): Promise<{ eventId: string }>; + redactEvent(eventId: string): Promise; + /** + * Live room events (not sticky ones — those reach the crate through its + * own sink), decrypted, redactions included, local echoes excluded. + */ + subscribeTimeline(listener: (event: TimelineEvent) => void): Unsubscribe; + /** + * Events already known that relate to `eventId` with the given relation + * type and event type — how a late joiner learns of a raised hand. + */ + getRelatedEvents( + eventId: string, + relType: string, + eventType: string, + ): TimelineEvent[]; +} + +export interface OwnProfile { + displayName: string | null; + /** An `mxc://` URL. */ + avatarUrl: string | null; +} + +/** The user's own profile. Editing is optional: a host may not allow it. */ +export interface ProfileDriver { + getOwnProfile(): OwnProfile; + subscribeOwnProfile(listener: (profile: OwnProfile) => void): Unsubscribe; + setDisplayName?(name: string): Promise; + setAvatar?(file: Blob): Promise; +} + +export interface MediaDriver { + /** + * A URL an `` can show for an `mxc://` thumbnail — possibly a `blob:` + * URL the driver fetched with its credentials — or null when the media + * cannot be resolved. + */ + thumbnailUrl( + mxcUrl: string, + width: number, + height: number, + resizeMethod: "crop" | "scale", + ): Promise; +} + +/** + * Everything Element Call asks of a Matrix client beyond MatrixRTC, bound to + * one room. One object, sliced into the capabilities above the way the crate + * slices its own driver, so a piece of Element Call can ask for no more than + * it needs. + */ +export interface ElementCallMatrixClientDriver + extends RoomDriver, TimelineDriver, ProfileDriver, MediaDriver { + /** Who we publish as. */ + readonly userId: string; + readonly deviceId: string; + /** The room this driver is bound to. */ + readonly roomId: string; + getCapabilities(): Promise; + /** Free-form facts for a rageshake: crypto version, sync state, and so on. */ + getDiagnostics?(): Promise>; +} diff --git a/src/driver/MockElementCallMatrixClientDriver.test.ts b/src/driver/MockElementCallMatrixClientDriver.test.ts new file mode 100644 index 000000000..2cf952c00 --- /dev/null +++ b/src/driver/MockElementCallMatrixClientDriver.test.ts @@ -0,0 +1,89 @@ +/* +Copyright 2026 Element Creations Ltd. + +SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial +Please see LICENSE in the repository root for full details. +*/ + +import { describe, expect, it, vi } from "vitest"; + +import { MockElementCallMatrixClientDriver } from "./MockElementCallMatrixClientDriver"; +import { MOCK_ROOM_ID } from "./MockRtcMatrixDriver"; + +describe("MockElementCallMatrixClientDriver", () => { + it("notifies room info, member and profile subscribers until unsubscribed", () => { + const driver = new MockElementCallMatrixClientDriver({ + roomInfo: { name: "Standup" }, + }); + expect(driver.getRoomInfo().name).toBe("Standup"); + const onInfo = vi.fn(); + const off = driver.subscribeRoomInfo(onInfo); + driver.setRoomInfo({ name: "Retro" }); + expect(onInfo).toHaveBeenCalledWith( + expect.objectContaining({ name: "Retro" }), + ); + off(); + driver.setRoomInfo({ name: "Planning" }); + expect(onInfo).toHaveBeenCalledTimes(1); + + const onMembers = vi.fn(); + driver.subscribeRoomMembers(onMembers); + const alice = { + userId: "@alice:example.org", + displayName: "Alice", + avatarUrl: null, + membership: "join" as const, + }; + driver.setRoomMembers([alice]); + expect(onMembers).toHaveBeenCalledWith([alice]); + expect(driver.getRoomMembers()).toEqual([alice]); + + const onProfile = vi.fn(); + driver.subscribeOwnProfile(onProfile); + driver.setOwnProfile({ displayName: "Bob" }); + expect(onProfile).toHaveBeenCalledWith({ + displayName: "Bob", + avatarUrl: null, + }); + }); + + it("records sent room events, echoes them, and resolves relations", async () => { + const driver = new MockElementCallMatrixClientDriver(); + const seen: string[] = []; + driver.subscribeTimeline((e) => seen.push(e.type)); + const { eventId } = await driver.sendRoomEvent("m.reaction", { + "m.relates_to": { + rel_type: "m.annotation", + event_id: "$membership", + key: "🖐️", + }, + }); + expect(driver.calls("sendRoomEvent")[0]).toMatchObject({ + eventType: "m.reaction", + eventId, + }); + expect(seen).toEqual(["m.reaction"]); + expect( + driver.getRelatedEvents("$membership", "m.annotation", "m.reaction"), + ).toHaveLength(1); + await driver.redactEvent(eventId); + expect(seen).toEqual(["m.reaction", "m.room.redaction"]); + expect( + driver.getRelatedEvents("$membership", "m.annotation", "m.reaction"), + ).toHaveLength(0); + }); + + it("answers thumbnails for mxc urls only", async () => { + const driver = new MockElementCallMatrixClientDriver(); + await expect( + driver.thumbnailUrl("mxc://example.org/abc", 96, 96, "crop"), + ).resolves.toContain("abc"); + await expect( + driver.thumbnailUrl("https://not-mxc", 96, 96, "crop"), + ).resolves.toBeNull(); + expect(driver.roomId).toBe(MOCK_ROOM_ID); + await expect(driver.getCapabilities()).resolves.toMatchObject({ + stickyEvents: true, + }); + }); +}); diff --git a/src/driver/MockElementCallMatrixClientDriver.ts b/src/driver/MockElementCallMatrixClientDriver.ts new file mode 100644 index 000000000..e52babd82 --- /dev/null +++ b/src/driver/MockElementCallMatrixClientDriver.ts @@ -0,0 +1,246 @@ +/* +Copyright 2026 Element Creations Ltd. + +SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial +Please see LICENSE in the repository root for full details. +*/ + +/** + * An {@link ElementCallMatrixClientDriver} whose room lives in memory, for + * tests and stories: room info, members, a timeline and a profile, with + * setters that notify subscribers, and a record of what was sent. + */ + +import { + type DriverCapabilities, + type ElementCallMatrixClientDriver, + type OwnProfile, + type RoomInfo, + type RoomMemberProfile, + type TimelineEvent, + type Unsubscribe, +} from "./ElementCallMatrixClientDriver"; +import { + MOCK_OWN_DEVICE_ID, + MOCK_OWN_USER_ID, + MOCK_ROOM_ID, +} from "./MockRtcMatrixDriver"; + +export type ClientCall = + | { + kind: "sendRoomEvent"; + eventType: string; + content: Record; + eventId: string; + } + | { kind: "redactEvent"; eventId: string }; + +export interface MockElementCallMatrixClientDriverOptions { + userId?: string; + deviceId?: string; + roomId?: string; + roomInfo?: Partial; + members?: RoomMemberProfile[]; + ownProfile?: Partial; + capabilities?: Partial; +} + +export class MockElementCallMatrixClientDriver implements ElementCallMatrixClientDriver { + public readonly userId: string; + public readonly deviceId: string; + public readonly roomId: string; + public readonly outbound: ClientCall[] = []; + + private capabilities: DriverCapabilities; + private roomInfo: RoomInfo; + private members: RoomMemberProfile[]; + private ownProfile: OwnProfile; + private readonly timeline: TimelineEvent[] = []; + + private readonly roomInfoListeners = new Set<(info: RoomInfo) => void>(); + private readonly memberListeners = new Set< + (members: RoomMemberProfile[]) => void + >(); + private readonly timelineListeners = new Set< + (event: TimelineEvent) => void + >(); + private readonly profileListeners = new Set<(profile: OwnProfile) => void>(); + private nextEventId = 0; + + public constructor(options: MockElementCallMatrixClientDriverOptions = {}) { + this.userId = options.userId ?? MOCK_OWN_USER_ID; + this.deviceId = options.deviceId ?? MOCK_OWN_DEVICE_ID; + this.roomId = options.roomId ?? MOCK_ROOM_ID; + this.capabilities = { + stickyEvents: true, + verifiedEventOrigins: true, + crossSigningVerdicts: true, + ...options.capabilities, + }; + this.roomInfo = { + name: "Test room", + canonicalAlias: null, + avatarUrl: null, + joinRule: "public", + encrypted: false, + canOpenSlot: true, + ...options.roomInfo, + }; + this.members = options.members ?? []; + this.ownProfile = { + displayName: "Me", + avatarUrl: null, + ...options.ownProfile, + }; + } + + public calls( + kind: K, + ): Extract[] { + return this.outbound.filter((c) => c.kind === kind) as Extract< + ClientCall, + { kind: K } + >[]; + } + + // --- room ------------------------------------------------------------------ + + public getRoomInfo(): RoomInfo { + return this.roomInfo; + } + + public subscribeRoomInfo(listener: (info: RoomInfo) => void): Unsubscribe { + return listen(this.roomInfoListeners, listener); + } + + public setRoomInfo(info: Partial): void { + this.roomInfo = { ...this.roomInfo, ...info }; + for (const l of this.roomInfoListeners) l(this.roomInfo); + } + + public getRoomMembers(): RoomMemberProfile[] { + return this.members; + } + + public subscribeRoomMembers( + listener: (members: RoomMemberProfile[]) => void, + ): Unsubscribe { + return listen(this.memberListeners, listener); + } + + public setRoomMembers(members: RoomMemberProfile[]): void { + this.members = members; + for (const l of this.memberListeners) l(members); + } + + // --- timeline -------------------------------------------------------------- + + public async sendRoomEvent( + eventType: string, + content: Record, + ): Promise<{ eventId: string }> { + const eventId = `$echo-${this.nextEventId++}`; + this.outbound.push({ kind: "sendRoomEvent", eventType, content, eventId }); + // Like sync, the room sees our event once the server has it. + this.emitTimelineEvent({ + eventId, + type: eventType, + sender: this.userId, + content, + originServerTs: Date.now(), + }); + return Promise.resolve({ eventId }); + } + + public async redactEvent(eventId: string): Promise { + this.outbound.push({ kind: "redactEvent", eventId }); + this.emitTimelineEvent({ + eventId: `$echo-${this.nextEventId++}`, + type: "m.room.redaction", + sender: this.userId, + content: { redacts: eventId }, + originServerTs: Date.now(), + redacts: eventId, + }); + return Promise.resolve(); + } + + public subscribeTimeline( + listener: (event: TimelineEvent) => void, + ): Unsubscribe { + return listen(this.timelineListeners, listener); + } + + /** A room event arrives from another user (or is echoed back). */ + public emitTimelineEvent(event: TimelineEvent): void { + this.timeline.push(event); + for (const l of this.timelineListeners) l(event); + } + + public getRelatedEvents( + eventId: string, + relType: string, + eventType: string, + ): TimelineEvent[] { + const redacted = new Set( + this.timeline.flatMap((e) => (e.redacts ? [e.redacts] : [])), + ); + return this.timeline.filter((e) => { + if (e.type !== eventType || redacted.has(e.eventId)) return false; + const relation = e.content["m.relates_to"] as + | { rel_type?: string; event_id?: string } + | undefined; + return relation?.rel_type === relType && relation.event_id === eventId; + }); + } + + // --- profile, media, capabilities -------------------------------------------- + + public getOwnProfile(): OwnProfile { + return this.ownProfile; + } + + public subscribeOwnProfile( + listener: (profile: OwnProfile) => void, + ): Unsubscribe { + return listen(this.profileListeners, listener); + } + + public setOwnProfile(profile: Partial): void { + this.ownProfile = { ...this.ownProfile, ...profile }; + for (const l of this.profileListeners) l(this.ownProfile); + } + + public async setDisplayName(name: string): Promise { + this.setOwnProfile({ displayName: name }); + return Promise.resolve(); + } + + public async thumbnailUrl( + mxcUrl: string, + width: number, + height: number, + _resizeMethod: "crop" | "scale", + ): Promise { + return Promise.resolve( + mxcUrl.startsWith("mxc://") + ? `https://media.example.org/thumbnail/${mxcUrl.slice("mxc://".length)}?width=${width}&height=${height}` + : null, + ); + } + + public async getCapabilities(): Promise { + return Promise.resolve(this.capabilities); + } + + public setCapabilities(capabilities: Partial): void { + this.capabilities = { ...this.capabilities, ...capabilities }; + } +} + +function listen(listeners: Set, listener: T): Unsubscribe { + listeners.add(listener); + return (): void => { + listeners.delete(listener); + }; +} diff --git a/src/driver/MockRtcMatrixDriver.test.ts b/src/driver/MockRtcMatrixDriver.test.ts new file mode 100644 index 000000000..39f87ce1c --- /dev/null +++ b/src/driver/MockRtcMatrixDriver.test.ts @@ -0,0 +1,171 @@ +/* +Copyright 2026 Element Creations Ltd. + +SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial +Please see LICENSE in the repository root for full details. +*/ + +import { beforeAll, describe, expect, it } from "vitest"; + +import { initMatrixRtcSdkForTests } from "../utils/test-matrix-rtc"; +import { + FfiElementCallCompat, + FfiMatrixDriver, + FfiMembershipState, + FfiParticipationManager, + FfiStatus, + FfiTransportIntent, + type FfiParticipationConfig, +} from "../matrix-rtc-sdk"; +import { + MOCK_LK_SERVICE_URL, + MOCK_OWN_USER_ID, + MOCK_SLOT_ID, + MockRtcMatrixDriver, + roomEncryptionEvent, + slotEvent, + waitFor, +} from "./MockRtcMatrixDriver"; + +const config: FfiParticipationConfig = { + compat: FfiElementCallCompat.StickyEvents, + manageMediaKeys: true, + requireCrossSignedSender: false, + useKeyDelayMs: 50n, +}; + +const joinParams = { + applicationType: "m.call", + intent: undefined, + stickyDurationMs: 240_000n, + keepAliveTimeoutMs: 15_000n, + degradedLifetimeMs: undefined, + delegateDelayedLeave: false, +}; + +const publish = (): FfiTransportIntent => + new FfiTransportIntent.Publish({ + transport: { + transportType: "livekit", + propertiesJson: JSON.stringify({ + livekit_service_url: MOCK_LK_SERVICE_URL, + }), + }, + }); + +function newManager(driver: MockRtcMatrixDriver): FfiParticipationManager { + return new FfiParticipationManager( + driver.roomId, + MOCK_SLOT_ID, + driver.userId, + driver.deviceId, + new FfiMatrixDriver(driver), + config, + ); +} + +describe("MockRtcMatrixDriver as the crate's driver", () => { + beforeAll(async () => { + await initMatrixRtcSdkForTests(); + }); + + it("echoes our sticky join so our own membership reaches the roster", async () => { + const driver = new MockRtcMatrixDriver({ + roomState: [slotEvent({ status: "open" })], + }); + const manager = newManager(driver); + await manager.join(publish(), joinParams); + expect(FfiStatus.Connected.instanceOf(manager.status())).toBe(true); + const sticky = driver.calls("stickyEvent"); + expect(sticky).toHaveLength(1); + expect(sticky[0].eventType).toBe("org.matrix.msc4143.rtc.member"); + const me = manager + .memberships() + .find((m) => m.member.userId === MOCK_OWN_USER_ID); + expect(me?.state).toBe(FfiMembershipState.Joined); + expect(me?.connections).toEqual([MOCK_LK_SERVICE_URL]); + expect(me?.transportIdentity).toBe(manager.ownTransportIdentity()); + // the token the mock minted is what the crate hands out + expect(manager.connections()[0].connection.jwtToken).toBe( + `jwt-for-${MOCK_LK_SERVICE_URL}`, + ); + await manager.leave(undefined, undefined); + manager.uniffiDestroy(); + }); + + it("hosts peers that join, answer our key and leave", async () => { + const driver = new MockRtcMatrixDriver({ + roomState: [ + roomEncryptionEvent(), + slotEvent({ status: "open", encrypted: true }), + ], + }); + const manager = newManager(driver); + const peer = driver.addPeer({ + userId: "@peer:example.org", + deviceId: "PEERDEV", + memberId: "m-peer", + }); + await manager.join( + new FfiTransportIntent.ReceiveOnly({ canSubscribe: ["livekit"] }), + joinParams, + ); + driver.peerJoins(peer); + expect(manager.memberships().map((m) => m.member.userId)).toContain( + peer.userId, + ); + await waitFor("key exchange", () => + manager.keyMap().some((k) => k.memberId === peer.memberId), + ); + // StickyEvents compat: our key went out in the deployed dialect + expect(driver.calls("toDevice")[0].eventType).toBe( + "io.element.call.encryption_keys", + ); + driver.peerLeaves(peer); + expect( + manager.memberships().find((m) => m.member.memberId === peer.memberId) + ?.state, + ).toBe(FfiMembershipState.LeftWithKeys); + await manager.leave(undefined, undefined); + manager.uniffiDestroy(); + }); + + it("reports homeserver connectivity into the crate", async () => { + const driver = new MockRtcMatrixDriver({ + roomState: [slotEvent({ status: "open" })], + }); + const manager = newManager(driver); + expect(manager.isHomeserverConnected()).toBe(true); + await manager.join(publish(), joinParams); + driver.setHomeserverConnected(false); + await waitFor("outage reported", () => !manager.isHomeserverConnected()); + await waitFor("impairment", () => { + const status = manager.status(); + return ( + FfiStatus.Connected.instanceOf(status) && + status.inner.impairments[0]?.tag === "HomeserverUnreachable" + ); + }); + driver.setHomeserverConnected(true); + await waitFor("outage clears", () => { + const status = manager.status(); + return ( + FfiStatus.Connected.instanceOf(status) && + status.inner.impairments.length === 0 + ); + }); + await manager.leave(undefined, undefined); + manager.uniffiDestroy(); + }); + + it("can refuse sticky and delayed events like an old homeserver", async () => { + const driver = new MockRtcMatrixDriver({ + roomState: [slotEvent({ status: "open" })], + }); + driver.refuseStickyEvents = true; + const manager = newManager(driver); + await expect(manager.join(publish(), joinParams)).rejects.toThrow(); + expect(FfiStatus.Disconnected.instanceOf(manager.status())).toBe(true); + manager.uniffiDestroy(); + }); +}); diff --git a/src/driver/MockRtcMatrixDriver.ts b/src/driver/MockRtcMatrixDriver.ts new file mode 100644 index 000000000..77f63ae57 --- /dev/null +++ b/src/driver/MockRtcMatrixDriver.ts @@ -0,0 +1,676 @@ +/* +Copyright 2026 Element Creations Ltd. + +SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial +Please see LICENSE in the repository root for full details. +*/ + +/** + * An {@link RtcMatrixDriver} with a homeserver made of arrays, for tests and + * stories. + * + * It models what sync would do: it records every outbound call, echoes + * accepted sticky and state events back through the room-event sink (so our + * own membership reaches the roster like anybody else's), answers `readState` + * from `roomState`, mints tokens, reports homeserver connectivity, and hosts + * simulated peers that answer our media key with theirs. + * + * A port of the crate's `web-test-app/src/mockDriver.ts`, which is the + * source of truth for the fabricated wire shapes below. + */ + +import { + FfiEventOrigin, + RtcError, + type ConnectivitySinkLike, + type FfiLivekitToken, + type FfiLivekitTokenRequest, + type FfiRtcTransport, + type FfiSendEventResponse, + type FfiToDeviceDelivery, + type FfiToDeviceRecipient, + type RoomEventSinkLike, + type StateUpdateSinkLike, + type ToDeviceSinkLike, +} from "../matrix-rtc-sdk"; +import { type RtcMatrixDriver } from "./RtcMatrixDriver"; + +export const MOCK_LK_SERVICE_URL = "https://lk.example.org"; +export const MOCK_ROOM_ID = "!room:example.org"; +/** MSC4143: a slot id is `{application_type}#{id}`; Element Call's is this. */ +export const MOCK_SLOT_ID = "m.call#ROOM"; +export const MOCK_OWN_USER_ID = "@me:example.org"; +export const MOCK_OWN_DEVICE_ID = "MYDEV"; + +/** Every call the crate made on the driver, in order. */ +export type OutboundCall = + | { + kind: "stickyEvent"; + roomId: string; + eventType: string; + content: Record; + durationMs: bigint; + } + | { + kind: "stateEvent"; + roomId: string; + eventType: string; + stateKey: string; + content: Record; + } + | { + kind: "delayedEvent"; + roomId: string; + eventType: string; + content: Record; + delayMs: bigint; + stickyDurationMs: bigint | undefined; + delayId: string; + } + | { + kind: "delayedStateEvent"; + roomId: string; + eventType: string; + stateKey: string; + content: Record; + delayMs: bigint; + delayId: string; + } + | { kind: "restartDelayed"; roomId: string; delayId: string } + | { kind: "cancelDelayed"; roomId: string; delayId: string } + | { + kind: "delegateDelayedLeave"; + roomId: string; + slotId: string; + delayId: string; + livekitServiceUrl: string | undefined; + delayMs: bigint; + } + | { + kind: "toDevice"; + recipients: FfiToDeviceRecipient[]; + eventType: string; + content: Record; + } + | { kind: "getRtcTransports" } + | { + kind: "getLivekitToken"; + url: string; + roomId: string; + slotId: string; + member: Record; + legacySfuGet: boolean; + }; + +/** A simulated remote participant. */ +export interface RemotePeer { + userId: string; + deviceId: string; + memberId: string; + /** 32 key bytes; defaults to a constant pattern. */ + key?: Uint8Array; +} + +/** A raw Matrix event as the crate reads it. */ +export type RawEvent = Record; + +export interface MockRtcMatrixDriverOptions { + userId?: string; + deviceId?: string; + roomId?: string; + /** Room state answered by `readState` (the crate's session seed). */ + roomState?: RawEvent[]; + /** Advertised by `getRtcTransports`; an empty list is "none". */ + transports?: FfiRtcTransport[]; +} + +export class MockRtcMatrixDriver implements RtcMatrixDriver { + /** Who this driver publishes as — not part of the contract, handy in tests. */ + public readonly userId: string; + public readonly deviceId: string; + public readonly roomId: string; + + public readonly outbound: OutboundCall[] = []; + /** Refuse delayed events like a homeserver without MSC4140 (404). */ + public refuseDelayedEvents = false; + /** Refuse sticky events like a homeserver without MSC4354 (404). */ + public refuseStickyEvents = false; + /** Make `getRtcTransports` fail rather than answer. */ + public failTransportDiscovery = false; + public roomState: RawEvent[]; + public transports: FfiRtcTransport[]; + /** Simulated peers answer our media key with theirs (index 0). */ + public readonly peers: RemotePeer[] = []; + + private roomEventSink?: RoomEventSinkLike; + private toDeviceSink?: ToDeviceSinkLike; + private stateUpdateSink?: StateUpdateSinkLike; + private connectivitySink?: ConnectivitySinkLike; + private homeserverConnected = true; + + private nextDelayId = 0; + private nextEventId = 0; + + public constructor(options: MockRtcMatrixDriverOptions = {}) { + this.userId = options.userId ?? MOCK_OWN_USER_ID; + this.deviceId = options.deviceId ?? MOCK_OWN_DEVICE_ID; + this.roomId = options.roomId ?? MOCK_ROOM_ID; + this.roomState = options.roomState ?? []; + this.transports = options.transports ?? [ + { + transportType: "livekit", + propertiesJson: JSON.stringify({ + livekit_service_url: MOCK_LK_SERVICE_URL, + }), + }, + ]; + } + + // --- assertions ---------------------------------------------------------- + + public calls( + kind: K, + ): Extract[] { + return this.outbound.filter((c) => c.kind === kind) as Extract< + OutboundCall, + { kind: K } + >[]; + } + + // --- outbound -------------------------------------------------------------- + + public async sendStickyEvent( + roomId: string, + eventType: string, + contentJson: string, + durationMs: bigint, + ): Promise { + const content = parse(contentJson); + this.record({ + kind: "stickyEvent", + roomId, + eventType, + content, + durationMs, + }); + if (this.refuseStickyEvents) + throw new RtcError.Unsupported( + "M_UNRECOGNIZED: sticky events are not supported", + ); + const eventId = this.eventId(); + // The homeserver echoes our event through sync. + this.echo( + { + type: eventType, + sender: this.userId, + event_id: eventId, + room_id: roomId, + origin_server_ts: Date.now(), + msc4354_sticky: { duration_ms: Number(durationMs) }, + content, + }, + new FfiEventOrigin.Encrypted({ senderDeviceId: this.deviceId }), + ); + return Promise.resolve({ eventId, delayId: undefined }); + } + + public async sendStateEvent( + roomId: string, + eventType: string, + stateKey: string, + contentJson: string, + ): Promise { + const content = parse(contentJson); + this.record({ kind: "stateEvent", roomId, eventType, stateKey, content }); + const eventId = this.eventId(); + this.echo( + { + type: eventType, + sender: this.userId, + event_id: eventId, + room_id: roomId, + state_key: stateKey, + origin_server_ts: Date.now(), + content, + }, + new FfiEventOrigin.Cleartext(), + ); + return Promise.resolve({ eventId, delayId: undefined }); + } + + public async sendDelayedEvent( + roomId: string, + eventType: string, + contentJson: string, + delayMs: bigint, + stickyDurationMs: bigint | undefined, + ): Promise { + const delayId = `delay-${this.nextDelayId++}`; + this.record({ + kind: "delayedEvent", + roomId, + eventType, + content: parse(contentJson), + delayMs, + stickyDurationMs, + delayId, + }); + if (this.refuseDelayedEvents) + // 404 M_UNRECOGNIZED: "this homeserver will never do delayed events". + throw new RtcError.Unsupported( + "M_UNRECOGNIZED: delayed events are not supported", + ); + return Promise.resolve(delayId); + } + + public async sendDelayedStateEvent( + roomId: string, + eventType: string, + stateKey: string, + contentJson: string, + delayMs: bigint, + ): Promise { + const delayId = `delay-${this.nextDelayId++}`; + this.record({ + kind: "delayedStateEvent", + roomId, + eventType, + stateKey, + content: parse(contentJson), + delayMs, + delayId, + }); + return Promise.resolve(delayId); + } + + public async restartDelayedEvent( + roomId: string, + delayId: string, + ): Promise { + this.record({ kind: "restartDelayed", roomId, delayId }); + return Promise.resolve(); + } + + public async cancelDelayedEvent( + roomId: string, + delayId: string, + ): Promise { + this.record({ kind: "cancelDelayed", roomId, delayId }); + return Promise.resolve(); + } + + public async delegateLivekitDelayedLeave( + roomId: string, + slotId: string, + _memberJson: string, + delayId: string, + livekitServiceUrl: string | undefined, + delayMs: bigint, + ): Promise { + this.record({ + kind: "delegateDelayedLeave", + roomId, + slotId, + delayId, + livekitServiceUrl, + delayMs, + }); + return Promise.resolve(); + } + + public async sendToDevice( + recipients: FfiToDeviceRecipient[], + eventType: string, + contentJson: string, + ): Promise { + this.record({ + kind: "toDevice", + recipients, + eventType, + content: parse(contentJson), + }); + // Simulated peers answer with their own key. + for (const recipient of recipients) { + const peer = this.peers.find( + (p) => + p.userId === recipient.userId && p.deviceId === recipient.deviceId, + ); + if (peer) queueMicrotask(() => this.peerSendsKey(peer, 0)); + } + // every recipient reachable + return Promise.resolve( + recipients.map((recipient) => ({ recipient, error: undefined })), + ); + } + + public async getRtcTransports(): Promise { + this.record({ kind: "getRtcTransports" }); + if (this.failTransportDiscovery) + throw new RtcError.Http("500: transports endpoint unavailable"); + return Promise.resolve(this.transports); + } + + public async getLivekitToken( + request: FfiLivekitTokenRequest, + ): Promise { + this.record({ + kind: "getLivekitToken", + url: request.url, + roomId: request.roomId, + slotId: request.slotId, + member: parse(request.memberJson), + legacySfuGet: request.legacySfuGet, + }); + return Promise.resolve({ + jwt: "jwt-for-" + request.url, + url: request.url.replace("https", "wss"), + }); + } + + public async readEvents(): Promise { + return Promise.resolve([]); + } + + public async readState( + eventType: string, + stateKey: string | undefined, + ): Promise { + return Promise.resolve( + this.roomState + .filter( + (e) => + e.type === eventType && + (stateKey === undefined || e.state_key === stateKey), + ) + .map((e) => JSON.stringify(e)), + ); + } + + // --- inbound sinks ----------------------------------------------------------- + // The crate subscribes exactly once, when its FfiMatrixDriver is built, and + // hands over sinks; a real driver hooks client listeners onto them. The + // mock stores them so tests can emit fabricated events. + + public subscribeRoomEvents(sink: RoomEventSinkLike): void { + this.roomEventSink = sink; + } + + public subscribeToDeviceEvents(sink: ToDeviceSinkLike): void { + this.toDeviceSink = sink; + } + + public subscribeStateUpdates(sink: StateUpdateSinkLike): void { + this.stateUpdateSink = sink; + } + + public subscribeConnectivity(sink: ConnectivitySinkLike): void { + this.connectivitySink = sink; + } + + public isHomeserverConnected(): boolean { + return this.homeserverConnected; + } + + /** The homeserver comes or goes, as a syncing client would report it. */ + public setHomeserverConnected(connected: boolean): void { + this.homeserverConnected = connected; + this.connectivitySink?.emit(connected); + } + + /** Emit any room event — sticky or state; the crate dispatches on type. */ + public emitRoomEvent(event: RawEvent, origin: FfiEventOrigin): boolean { + if (!this.roomEventSink) + throw new Error("The SDK has not subscribed to room events"); + return this.roomEventSink.emit(JSON.stringify(event), origin); + } + + /** `senderCrossSigned` is the MSC4153 verdict; peers are cross-signed by default. */ + public emitToDevice( + eventType: string, + sender: string, + content: RawEvent, + origin: FfiEventOrigin, + senderCrossSigned: boolean | undefined = true, + ): boolean { + if (!this.toDeviceSink) + throw new Error("The SDK has not subscribed to to-device events"); + return this.toDeviceSink.emit( + eventType, + sender, + JSON.stringify(content), + origin, + senderCrossSigned, + ); + } + + public emitStateUpdate(events: RawEvent[]): boolean { + if (!this.stateUpdateSink) + throw new Error("The SDK has not subscribed to state updates"); + return this.stateUpdateSink.emit(events.map((e) => JSON.stringify(e))); + } + + // --- simulated peers -------------------------------------------------------- + + public addPeer(peer: RemotePeer): RemotePeer { + this.peers.push(peer); + return peer; + } + + /** The peer publishes a join (on `MOCK_LK_SERVICE_URL` unless given). */ + public peerJoins( + peer: RemotePeer, + opts: { lkServiceUrl?: string; durationMs?: number } = {}, + ): boolean { + return this.emitRoomEvent( + memberJoinEvent({ + roomId: this.roomId, + userId: peer.userId, + memberId: peer.memberId, + ...opts, + }), + new FfiEventOrigin.Encrypted({ senderDeviceId: peer.deviceId }), + ); + } + + public peerLeaves(peer: RemotePeer): boolean { + return this.emitRoomEvent( + memberLeaveEvent({ + roomId: this.roomId, + userId: peer.userId, + memberId: peer.memberId, + }), + new FfiEventOrigin.Encrypted({ senderDeviceId: peer.deviceId }), + ); + } + + public peerSendsKey(peer: RemotePeer, index: number): boolean { + return this.emitToDevice( + "m.rtc.encryption_key", + peer.userId, + encryptionKeyContent({ + roomId: this.roomId, + memberId: peer.memberId, + index, + key: peer.key, + }), + new FfiEventOrigin.Encrypted({ senderDeviceId: peer.deviceId }), + ); + } + + // --- internals ----------------------------------------------------------------- + + private record(call: OutboundCall): void { + this.outbound.push(call); + } + + private eventId(): string { + return `$echo-${this.nextEventId++}`; + } + + private echo(event: RawEvent, origin: FfiEventOrigin): void { + this.roomEventSink?.emit(JSON.stringify(event), origin); + } +} + +function parse(json: string): Record { + return JSON.parse(json) as Record; +} + +// --------------------------------------------------------------------------- +// Inbound event fabrication — the MSC4143/MSC4354 wire shapes the crate's +// dispatch reads (see its src/session/dispatch.rs). Adjust here, not in +// every test. +// --------------------------------------------------------------------------- + +let eventCounter = 0; + +export function memberJoinEvent(opts: { + roomId?: string; + userId: string; + memberId: string; + lkServiceUrl?: string; + durationMs?: number; +}): RawEvent { + return { + type: "m.rtc.member", + sender: opts.userId, + event_id: `$ev-${eventCounter++}`, + room_id: opts.roomId ?? MOCK_ROOM_ID, + origin_server_ts: Date.now(), + msc4354_sticky: { duration_ms: opts.durationMs ?? 240_000 }, + content: { + slot_id: MOCK_SLOT_ID, + // MSC4354: the sticky key lives in the content and equals member.id. + msc4354_sticky_key: opts.memberId, + member: { id: opts.memberId, membership: "join" }, + application: { type: "m.call" }, + transports: { + published: [ + { + type: "livekit", + livekit_service_url: opts.lkServiceUrl ?? MOCK_LK_SERVICE_URL, + }, + ], + can_subscribe: ["livekit"], + }, + }, + }; +} + +export function memberLeaveEvent(opts: { + roomId?: string; + userId: string; + memberId: string; +}): RawEvent { + return { + type: "m.rtc.member", + sender: opts.userId, + event_id: `$ev-${eventCounter++}`, + room_id: opts.roomId ?? MOCK_ROOM_ID, + origin_server_ts: Date.now(), + msc4354_sticky: { duration_ms: 240_000 }, + content: { + slot_id: MOCK_SLOT_ID, + msc4354_sticky_key: opts.memberId, + member: { id: opts.memberId, membership: "leave" }, + leave_reason: { code: "leave" }, + }, + }; +} + +export function slotEvent( + opts: { roomId?: string; status: "open" | "closed"; encrypted?: boolean } = { + status: "open", + }, +): RawEvent { + const content: Record = { + status: opts.status, + application: { type: "m.call" }, + }; + if (opts.encrypted) content.encryption = { type: "m.per_member" }; + return { + type: "m.rtc.slot", + sender: "@admin:example.org", + event_id: `$ev-${eventCounter++}`, + room_id: opts.roomId ?? MOCK_ROOM_ID, + state_key: MOCK_SLOT_ID, + origin_server_ts: Date.now(), + content, + }; +} + +export function roomEncryptionEvent(roomId = MOCK_ROOM_ID): RawEvent { + return { + type: "m.room.encryption", + sender: "@admin:example.org", + event_id: `$ev-${eventCounter++}`, + room_id: roomId, + state_key: "", + origin_server_ts: Date.now(), + content: { algorithm: "m.megolm.v1.aes-sha2" }, + }; +} + +/** `m.room.member` state with the profile fields the crate puts on a member. */ +export function roomMemberEvent(opts: { + roomId?: string; + userId: string; + membership?: "join" | "invite" | "leave"; + displayName?: string; + avatarUrl?: string; +}): RawEvent { + const content: Record = { + membership: opts.membership ?? "join", + }; + if (opts.displayName !== undefined) content.displayname = opts.displayName; + if (opts.avatarUrl !== undefined) content.avatar_url = opts.avatarUrl; + return { + type: "m.room.member", + sender: opts.userId, + event_id: `$ev-${eventCounter++}`, + room_id: opts.roomId ?? MOCK_ROOM_ID, + state_key: opts.userId, + origin_server_ts: Date.now(), + content, + }; +} + +const DEFAULT_KEY = new Uint8Array(32).fill(7); + +function base64(bytes: Uint8Array): string { + let binary = ""; + for (const b of bytes) binary += String.fromCharCode(b); + return btoa(binary).replace(/=+$/, ""); +} + +/** MSC4143 `m.rtc.encryption_key` content. */ +export function encryptionKeyContent(opts: { + roomId?: string; + memberId: string; + index: number; + key?: Uint8Array; +}): RawEvent { + return { + room_id: opts.roomId ?? MOCK_ROOM_ID, + member_id: opts.memberId, + media_key: { index: opts.index, key: base64(opts.key ?? DEFAULT_KEY) }, + format: 0, + }; +} + +/** One timer tick: the crate's listener callbacks arrive after the emitting task yields. */ +export const tick = async (): Promise => + new Promise((resolve) => setTimeout(resolve, 0)); + +export async function waitFor( + what: string, + cond: () => boolean, + timeoutMs = 3000, +): Promise { + const deadline = Date.now() + timeoutMs; + while (!cond()) { + if (Date.now() > deadline) + throw new Error(`Timed out waiting for: ${what}`); + await new Promise((r) => setTimeout(r, 10)); + } +} diff --git a/src/driver/RtcMatrixDriver.ts b/src/driver/RtcMatrixDriver.ts new file mode 100644 index 000000000..19bd1026c --- /dev/null +++ b/src/driver/RtcMatrixDriver.ts @@ -0,0 +1,21 @@ +/* +Copyright 2026 Element Creations Ltd. + +SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial +Please see LICENSE in the repository root for full details. +*/ + +/** + * The MatrixRTC half of what a host supplies: the `matrix-rtc` crate's own + * driver contract, taken verbatim from its bindings. Everything MatrixRTC — + * sticky and delayed events, to-device key delivery, transport tokens, the + * inbound event sinks and homeserver connectivity — goes through this and + * is consumed by the crate, never by Element Call directly. + * + * What a call needs from a Matrix client beyond MatrixRTC is the separate + * {@link ElementCallMatrixClientDriver}. + */ + +import { type MatrixDriverCallback } from "../matrix-rtc-sdk"; + +export type RtcMatrixDriver = MatrixDriverCallback; diff --git a/src/driver/jsSdk/JsSdkElementCallMatrixClientDriver.test.ts b/src/driver/jsSdk/JsSdkElementCallMatrixClientDriver.test.ts new file mode 100644 index 000000000..cabb136d8 --- /dev/null +++ b/src/driver/jsSdk/JsSdkElementCallMatrixClientDriver.test.ts @@ -0,0 +1,123 @@ +/* +Copyright 2026 Element Creations Ltd. + +SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial +Please see LICENSE in the repository root for full details. +*/ + +import { MatrixEvent, RoomEvent, UserEvent } from "matrix-js-sdk"; +import { describe, expect, it, vi } from "vitest"; + +import { JsSdkElementCallMatrixClientDriver } from "./JsSdkElementCallMatrixClientDriver"; +import { + ME, + ROOM_ID, + asClient, + asRoom, + fakeClient, + fakeRoom, +} from "./jsSdkTestFakes"; + +describe("JsSdkElementCallMatrixClientDriver", () => { + it("serves room info, members, timeline and profile from a full client", async () => { + const client = fakeClient(false); + const room = fakeRoom(); + const driver = new JsSdkElementCallMatrixClientDriver( + asClient(client), + asRoom(room), + ); + expect(driver.userId).toBe(ME); + expect(driver.getRoomInfo()).toEqual({ + name: "Standup", + canonicalAlias: "#standup:example.org", + avatarUrl: "mxc://example.org/room", + joinRule: "public", + encrypted: true, + canOpenSlot: true, + }); + const onInfo = vi.fn(); + const offInfo = driver.subscribeRoomInfo(onInfo); + room.name = "Retro"; + room.emit(RoomEvent.Name, room); + expect(onInfo).toHaveBeenCalledWith( + expect.objectContaining({ name: "Retro" }), + ); + offInfo(); + + expect(driver.getRoomMembers()).toEqual([ + { + userId: "@a:example.org", + displayName: "Alice", + avatarUrl: "mxc://example.org/alice", + membership: "join", + }, + { + userId: "@b:example.org", + displayName: null, + avatarUrl: null, + membership: "invite", + }, + ]); + + const seen: string[] = []; + driver.subscribeTimeline((e) => seen.push(`${e.type}:${e.eventId}`)); + const reaction = new MatrixEvent({ + type: "m.reaction", + sender: "@a:example.org", + event_id: "$r1", + room_id: ROOM_ID, + origin_server_ts: 3, + content: { "m.relates_to": { rel_type: "m.annotation", key: "🖐️" } }, + }); + client.emit(RoomEvent.Timeline, reaction, room, false, false, {}); + client.emit(RoomEvent.Timeline, reaction, room, false, false, {}); + await vi.waitFor(() => expect(seen).toEqual(["m.reaction:$r1"])); + + await driver.sendRoomEvent("io.element.call.reaction", { emoji: "🎉" }); + expect(client.sendEvent).toHaveBeenCalledWith( + ROOM_ID, + "io.element.call.reaction", + { emoji: "🎉" }, + ); + await driver.redactEvent("$r1"); + expect(client.redactEvent).toHaveBeenCalledWith(ROOM_ID, "$r1"); + + expect(driver.getOwnProfile()).toEqual({ + displayName: "Me", + avatarUrl: "mxc://example.org/me", + }); + const onProfile = vi.fn(); + driver.subscribeOwnProfile(onProfile); + const user = client.getUser(ME)!; + user.rawDisplayName = "Moi"; + user.emit(UserEvent.DisplayName, undefined, user); + expect(onProfile).toHaveBeenCalledWith( + expect.objectContaining({ displayName: "Moi" }), + ); + + await expect(driver.getCapabilities()).resolves.toEqual({ + stickyEvents: true, + verifiedEventOrigins: true, + crossSigningVerdicts: true, + }); + await expect(driver.getDiagnostics()).resolves.toMatchObject({ + matrix_backend: "jssdk", + crypto_version: "fake 1.0", + }); + }); + + it("says what a widget client cannot vouch for and leaves media to the host bridge", async () => { + const driver = new JsSdkElementCallMatrixClientDriver( + asClient(fakeClient(true)), + asRoom(fakeRoom()), + ); + await expect(driver.getCapabilities()).resolves.toMatchObject({ + verifiedEventOrigins: false, + crossSigningVerdicts: false, + }); + // no token of its own: media comes through the host bridge instead + await expect( + driver.thumbnailUrl("mxc://example.org/x", 96, 96, "crop"), + ).resolves.toBeNull(); + }); +}); diff --git a/src/driver/jsSdk/JsSdkElementCallMatrixClientDriver.ts b/src/driver/jsSdk/JsSdkElementCallMatrixClientDriver.ts new file mode 100644 index 000000000..32b6bbc76 --- /dev/null +++ b/src/driver/jsSdk/JsSdkElementCallMatrixClientDriver.ts @@ -0,0 +1,329 @@ +/* +Copyright 2026 Element Creations Ltd. + +SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial +Please see LICENSE in the repository root for full details. +*/ + +/** + * An {@link ElementCallMatrixClientDriver} over a matrix-js-sdk client: room + * metadata and members, the room's timeline for reactions and notifications, + * the user's own profile, authenticated thumbnails and capability probes. + * Works on a full `MatrixClient` and on a `RoomWidgetClient`; the places + * they differ are marked "widget". + */ + +import { + KnownMembership, + type MatrixClient, + type MatrixEvent, + type Room, + RoomEvent, + type RoomMember, + RoomStateEvent, + RoomWidgetClient, + UNSTABLE_MSC4354_STICKY_EVENTS, + type User, + UserEvent, +} from "matrix-js-sdk"; +import { logger as rootLogger, type Logger } from "matrix-js-sdk/lib/logger"; + +import { ELEMENT_CALL_SLOT_EVENT_TYPE } from "../../state/rtc/slot"; +import { + type DriverCapabilities, + type ElementCallMatrixClientDriver, + type OwnProfile, + type RoomInfo, + type RoomMemberProfile, + type TimelineEvent, + type Unsubscribe, +} from "../ElementCallMatrixClientDriver"; + +/** The state event types `getRoomInfo()` is computed from. */ +const ROOM_INFO_EVENT_TYPES = new Set([ + "m.room.name", + "m.room.avatar", + "m.room.canonical_alias", + "m.room.join_rules", + "m.room.encryption", + "m.room.power_levels", +]); + +export interface JsSdkElementCallMatrixClientDriverOptions { + logger?: Logger; +} + +export class JsSdkElementCallMatrixClientDriver implements ElementCallMatrixClientDriver { + public readonly userId: string; + public readonly deviceId: string; + public readonly roomId: string; + + private readonly logger: Logger; + /** Widget: no crypto backend, no access token, events without metadata. */ + private readonly widget: boolean; + private capabilities: Promise | null = null; + + public constructor( + private readonly client: MatrixClient, + private readonly room: Room, + options: JsSdkElementCallMatrixClientDriverOptions = {}, + ) { + const userId = client.getUserId(); + const deviceId = client.getDeviceId(); + if (userId === null || deviceId === null) + throw new Error( + "The client must be logged in before it can drive a call", + ); + this.userId = userId; + this.deviceId = deviceId; + this.roomId = room.roomId; + this.widget = client instanceof RoomWidgetClient; + this.logger = (options.logger ?? rootLogger).getChild( + `[JsSdkElementCallMatrixClientDriver ${room.roomId}]`, + ); + } + + // --- room ------------------------------------------------------------------ + + public getRoomInfo(): RoomInfo { + return { + name: this.room.name, + canonicalAlias: this.room.getCanonicalAlias(), + avatarUrl: this.room.getMxcAvatarUrl(), + joinRule: this.room.currentState.getJoinRule() ?? null, + encrypted: this.room.hasEncryptionStateEvent(), + canOpenSlot: this.room.currentState.maySendStateEvent( + ELEMENT_CALL_SLOT_EVENT_TYPE, + this.userId, + ), + }; + } + + public subscribeRoomInfo(listener: (info: RoomInfo) => void): Unsubscribe { + const notify = (): void => listener(this.getRoomInfo()); + const onState = (event: MatrixEvent): void => { + if ( + event.getRoomId() === this.roomId && + ROOM_INFO_EVENT_TYPES.has(event.getType()) + ) + notify(); + }; + this.room.on(RoomEvent.Name, notify); + this.client.on(RoomStateEvent.Events, onState); + return (): void => { + this.room.off(RoomEvent.Name, notify); + this.client.off(RoomStateEvent.Events, onState); + }; + } + + public getRoomMembers(): RoomMemberProfile[] { + const profile = + (membership: "join" | "invite") => + (member: RoomMember): RoomMemberProfile => ({ + userId: member.userId, + displayName: member.rawDisplayName ?? null, + avatarUrl: member.getMxcAvatarUrl() ?? null, + membership, + }); + return [ + ...this.room + .getMembersWithMembership(KnownMembership.Join) + .map(profile("join")), + ...this.room + .getMembersWithMembership(KnownMembership.Invite) + .map(profile("invite")), + ]; + } + + public subscribeRoomMembers( + listener: (members: RoomMemberProfile[]) => void, + ): Unsubscribe { + const onMembers = (event: MatrixEvent): void => { + if (event.getRoomId() === this.roomId) listener(this.getRoomMembers()); + }; + this.client.on(RoomStateEvent.Members, onMembers); + return (): void => { + this.client.off(RoomStateEvent.Members, onMembers); + }; + } + + // --- timeline ---------------------------------------------------------------- + + public async sendRoomEvent( + eventType: string, + content: Record, + ): Promise<{ eventId: string }> { + const res = await this.client.sendEvent( + this.roomId, + eventType as never, + content as never, + ); + return { eventId: res.event_id }; + } + + public async redactEvent(eventId: string): Promise { + await this.client.redactEvent(this.roomId, eventId); + } + + public subscribeTimeline( + listener: (event: TimelineEvent) => void, + ): Unsubscribe { + // Our own events are seen twice — as the local echo, then as sent — + // and a redaction is both a timeline event and a Redaction signal. + const seen = new Set(); + const deliver = async (event: MatrixEvent): Promise => { + if (event.getRoomId() !== this.roomId) return; + // Still sending: the LocalEchoUpdated listener gets the real id later. + if (event.status !== null) return; + if (event.unstableStickyInfo !== undefined || event.isState()) return; + const eventId = event.getId(); + const sender = event.getSender(); + if (!eventId || !sender || seen.has(eventId)) return; + try { + await this.client.decryptEventIfNeeded(event); + } catch (e) { + this.logger.warn(`Could not decrypt ${eventId}`, e); + } + if (event.isDecryptionFailure() || seen.has(eventId)) return; + seen.add(eventId); + if (seen.size > 1000) seen.delete(seen.values().next().value!); + listener({ + eventId, + type: event.getType(), + sender, + content: event.getContent(), + originServerTs: event.getTs(), + redacts: event.event.redacts, + }); + }; + const onTimeline = ( + event: MatrixEvent, + room: Room | undefined, + toStartOfTimeline: boolean | undefined, + ): void => { + if (room?.roomId === this.roomId && !toStartOfTimeline) + void deliver(event); + }; + const onEcho = (event: MatrixEvent): void => void deliver(event); + this.client.on(RoomEvent.Timeline, onTimeline); + this.room.on(RoomEvent.LocalEchoUpdated, onEcho); + this.room.on(RoomEvent.Redaction, onEcho); + return (): void => { + this.client.off(RoomEvent.Timeline, onTimeline); + this.room.off(RoomEvent.LocalEchoUpdated, onEcho); + this.room.off(RoomEvent.Redaction, onEcho); + }; + } + + public getRelatedEvents( + eventId: string, + relType: string, + eventType: string, + ): TimelineEvent[] { + const relations = this.room.relations.getChildEventsForEvent( + eventId, + relType as never, + eventType as never, + ); + return (relations?.getRelations() ?? []) + .filter( + (event) => !event.isRedacted() && event.getId() && event.getSender(), + ) + .map((event) => ({ + eventId: event.getId()!, + type: event.getType(), + sender: event.getSender()!, + content: event.getContent(), + originServerTs: event.getTs(), + })); + } + + // --- profile ------------------------------------------------------------------- + + public getOwnProfile(): OwnProfile { + const user = this.client.getUser(this.userId); + return { + displayName: user?.rawDisplayName ?? null, + avatarUrl: user?.avatarUrl ?? null, + }; + } + + public subscribeOwnProfile( + listener: (profile: OwnProfile) => void, + ): Unsubscribe { + const user: User | null = this.client.getUser(this.userId); + if (user === null) return (): void => {}; + const notify = (): void => listener(this.getOwnProfile()); + user.on(UserEvent.DisplayName, notify); + user.on(UserEvent.AvatarUrl, notify); + return (): void => { + user.off(UserEvent.DisplayName, notify); + user.off(UserEvent.AvatarUrl, notify); + }; + } + + public async setDisplayName(name: string): Promise { + await this.client.setDisplayName(name); + } + + public async setAvatar(file: Blob): Promise { + const { content_uri: uri } = await this.client.uploadContent(file); + await this.client.setAvatarUrl(uri); + } + + // --- media ----------------------------------------------------------------------- + + public async thumbnailUrl( + mxcUrl: string, + width: number, + height: number, + resizeMethod: "crop" | "scale", + ): Promise { + const httpUrl = this.client.mxcUrlToHttp( + mxcUrl, + width, + height, + resizeMethod, + false, + true, + true, + ); + // Widget: no token of our own; the host bridge downloads media instead. + const token = this.client.getAccessToken(); + if (httpUrl === null || token === null) return null; + const response = await fetch(httpUrl, { + headers: { Authorization: `Bearer ${token}` }, + }); + if (!response.ok) return null; + return URL.createObjectURL(await response.blob()); + } + + // --- capabilities and diagnostics ------------------------------------------------ + + public async getCapabilities(): Promise { + this.capabilities ??= this.probeCapabilities(); + return this.capabilities; + } + + private async probeCapabilities(): Promise { + const stickyEvents = await this.client + .doesServerSupportUnstableFeature(UNSTABLE_MSC4354_STICKY_EVENTS) + .catch((e: unknown) => { + this.logger.warn("Could not probe sticky event support", e); + return false; + }); + return { + stickyEvents, + verifiedEventOrigins: !this.widget, + crossSigningVerdicts: this.client.getCrypto() !== undefined, + }; + } + + public async getDiagnostics(): Promise> { + return Promise.resolve({ + matrix_backend: this.widget ? "widget" : "jssdk", + crypto_version: this.client.getCrypto()?.getVersion() ?? "none", + sync_state: String(this.client.getSyncState()), + }); + } +} diff --git a/src/driver/jsSdk/JsSdkRtcMatrixDriver.test.ts b/src/driver/jsSdk/JsSdkRtcMatrixDriver.test.ts new file mode 100644 index 000000000..130fbfb98 --- /dev/null +++ b/src/driver/jsSdk/JsSdkRtcMatrixDriver.test.ts @@ -0,0 +1,488 @@ +/* +Copyright 2026 Element Creations Ltd. + +SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial +Please see LICENSE in the repository root for full details. +*/ + +import { + ClientEvent, + MatrixError, + MatrixEvent, + RoomStateEvent, + RoomStickyEventsEvent, + SyncState, + UnsupportedStickyEventsEndpointError, + UpdateDelayedEventAction, +} from "matrix-js-sdk"; +import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; + +import { initMatrixRtcSdkForTests } from "../../utils/test-matrix-rtc"; +import { + FfiEventOrigin, + RtcError, + type ConnectivitySinkLike, + type RoomEventSinkLike, + type StateUpdateSinkLike, + type ToDeviceSinkLike, +} from "../../matrix-rtc-sdk"; +import { JsSdkRtcMatrixDriver } from "./JsSdkRtcMatrixDriver"; +import { + LK, + ME, + MY_DEVICE, + ROOM_ID, + asClient, + asRoom, + fakeClient, + fakeRoom, + jsonResponse, + openIdToken, + type FakeClient, + type FakeRoom, +} from "./jsSdkTestFakes"; + +const memberJson = JSON.stringify({ + id: "m-1", + claimed_user_id: ME, + claimed_device_id: MY_DEVICE, +}); + +let fetchMock: ReturnType>; + +describe("JsSdkRtcMatrixDriver", () => { + beforeEach(async () => { + // The bindings define the RtcError classes the driver throws. + await initMatrixRtcSdkForTests(); + fetchMock = vi.fn(); + vi.stubGlobal("fetch", fetchMock); + }); + afterEach(() => { + vi.unstubAllGlobals(); + }); + + describe("over a full MatrixClient", () => { + it("sends sticky, delayed and state events through the unstable APIs", async () => { + const { client, driver } = fullClient(); + await expect( + driver.sendStickyEvent(ROOM_ID, "m.rtc.member", '{"a":1}', 240_000n), + ).resolves.toEqual({ eventId: "$sticky", delayId: undefined }); + expect(client._unstable_sendStickyEvent).toHaveBeenCalledWith( + ROOM_ID, + 240_000, + null, + "m.rtc.member", + { a: 1 }, + ); + + await expect( + driver.sendDelayedEvent( + ROOM_ID, + "m.rtc.member", + "{}", + 15_000n, + 240_000n, + ), + ).resolves.toBe("delay-sticky"); + expect(client._unstable_sendStickyDelayedEvent).toHaveBeenCalledWith( + ROOM_ID, + 240_000, + { delay: 15_000 }, + null, + "m.rtc.member", + {}, + ); + await expect( + driver.sendDelayedEvent( + ROOM_ID, + "m.rtc.member", + "{}", + 15_000n, + undefined, + ), + ).resolves.toBe("delay-plain"); + expect(client._unstable_sendDelayedEvent).toHaveBeenCalledWith( + ROOM_ID, + { delay: 15_000 }, + null, + "m.rtc.member", + {}, + ); + + await driver.sendDelayedStateEvent(ROOM_ID, "m.x", "key", "{}", 5_000n); + expect(client._unstable_sendDelayedStateEvent).toHaveBeenCalledWith( + ROOM_ID, + { delay: 5_000 }, + "m.x", + {}, + "key", + ); + await driver.sendStateEvent(ROOM_ID, "m.rtc.slot", "m.call#ROOM", "{}"); + expect(client.sendStateEvent).toHaveBeenCalledWith( + ROOM_ID, + "m.rtc.slot", + {}, + "m.call#ROOM", + ); + + await driver.restartDelayedEvent(ROOM_ID, "d1"); + await driver.cancelDelayedEvent(ROOM_ID, "d1"); + expect(client._unstable_updateDelayedEvent).toHaveBeenNthCalledWith( + 1, + "d1", + UpdateDelayedEventAction.Restart, + ); + expect(client._unstable_updateDelayedEvent).toHaveBeenNthCalledWith( + 2, + "d1", + UpdateDelayedEventAction.Cancel, + ); + }); + + it("maps js-sdk failures onto the crate's error family", async () => { + const { client, driver } = fullClient(); + client._unstable_sendStickyEvent.mockRejectedValueOnce( + new UnsupportedStickyEventsEndpointError("nope", "sendStickyEvent"), + ); + await expect( + driver.sendStickyEvent(ROOM_ID, "m.rtc.member", "{}", 1n), + ).rejects.toSatisfy((e) => RtcError.Unsupported.instanceOf(e)); + + client.sendStateEvent.mockRejectedValueOnce( + new MatrixError({ errcode: "M_FORBIDDEN" }, 403), + ); + await expect( + driver.sendStateEvent(ROOM_ID, "m.rtc.slot", "k", "{}"), + ).rejects.toSatisfy((e) => RtcError.Rejected.instanceOf(e)); + + client.sendStateEvent.mockRejectedValueOnce( + new MatrixError( + { errcode: "M_LIMIT_EXCEEDED", retry_after_ms: 1500 }, + 429, + ), + ); + await expect( + driver.sendStateEvent(ROOM_ID, "m.rtc.slot", "k", "{}"), + ).rejects.toSatisfy( + (e) => + RtcError.RateLimited.instanceOf(e) && e.inner.retryAfterMs === 1500n, + ); + }); + + it("sends to-device messages Olm-encrypted per device", async () => { + const { client, driver } = fullClient(); + const recipients = [{ userId: "@a:example.org", deviceId: "ADEV" }]; + await expect( + driver.sendToDevice(recipients, "m.rtc.encryption_key", '{"k":1}'), + ).resolves.toEqual([{ recipient: recipients[0], error: undefined }]); + expect(client.encryptAndSendToDevice).toHaveBeenCalledWith( + "m.rtc.encryption_key", + recipients, + { k: 1 }, + ); + }); + + it("discovers transports through the client and answers in the crate's shape", async () => { + const { client, driver } = fullClient(); + client._unstable_getRTCTransports.mockResolvedValue([ + { type: "livekit", livekit_service_url: LK }, + ]); + await expect(driver.getRtcTransports()).resolves.toEqual([ + { + transportType: "livekit", + propertiesJson: JSON.stringify({ livekit_service_url: LK }), + }, + ]); + }); + + it("exchanges an OpenID token for a LiveKit token, on either endpoint", async () => { + const { driver } = fullClient(); + // a fresh Response per call: a body can be read once + fetchMock.mockImplementation(async () => + Promise.resolve(jsonResponse({ jwt: "the-jwt", url: "wss://sfu" })), + ); + await expect( + driver.getLivekitToken({ + url: LK, + roomId: ROOM_ID, + slotId: "m.call#ROOM", + memberJson, + legacySfuGet: false, + }), + ).resolves.toEqual({ jwt: "the-jwt", url: "wss://sfu" }); + const [endpoint, init] = fetchMock.mock.calls[0] as unknown as [ + string, + RequestInit, + ]; + expect(endpoint).toBe(`${LK}/get_token`); + expect(JSON.parse(init.body as string)).toEqual({ + room_id: ROOM_ID, + slot_id: "m.call#ROOM", + openid_token: openIdToken, + member: JSON.parse(memberJson), + }); + + await driver.getLivekitToken({ + url: LK, + roomId: ROOM_ID, + slotId: "m.call#ROOM", + memberJson, + legacySfuGet: true, + }); + const [legacyEndpoint, legacyInit] = fetchMock.mock + .calls[1] as unknown as [string, RequestInit]; + expect(legacyEndpoint).toBe(`${LK}/sfu/get`); + expect(JSON.parse(legacyInit.body as string)).toEqual({ + room: ROOM_ID, + openid_token: openIdToken, + device_id: MY_DEVICE, + }); + + fetchMock.mockResolvedValueOnce(new Response("gone", { status: 404 })); + await expect( + driver.getLivekitToken({ + url: LK, + roomId: ROOM_ID, + slotId: "m.call#ROOM", + memberJson, + legacySfuGet: false, + }), + ).rejects.toSatisfy((e) => RtcError.Unsupported.instanceOf(e)); + }); + + it("delegates the delayed leave through the authorisation service's token endpoint", async () => { + const { driver } = fullClient(); + fetchMock.mockImplementation(async () => + Promise.resolve(jsonResponse({ jwt: "discarded" })), + ); + await driver.delegateLivekitDelayedLeave( + ROOM_ID, + "m.call#ROOM", + memberJson, + "delay-1", + LK, + 3_600_000n, + ); + const [endpoint, init] = fetchMock.mock.calls[0] as unknown as [ + string, + RequestInit, + ]; + expect(endpoint).toBe(`${LK}/get_token`); + expect(JSON.parse(init.body as string)).toMatchObject({ + delay_id: "delay-1", + delay_timeout: 3_600_000, + delay_cs_api_url: "https://hs.example.org", + }); + // receive-only: nothing to delegate to + await expect( + driver.delegateLivekitDelayedLeave( + ROOM_ID, + "m.call#ROOM", + memberJson, + "delay-1", + undefined, + 1n, + ), + ).rejects.toSatisfy((e) => RtcError.Unsupported.instanceOf(e)); + }); + + it("feeds sticky events and state updates into the crate's sinks with their origin", async () => { + const { client, room, driver } = fullClient(); + const roomSink = sink(); + const stateSink = sink(); + driver.subscribeRoomEvents(roomSink as unknown as RoomEventSinkLike); + driver.subscribeStateUpdates(stateSink as unknown as StateUpdateSinkLike); + + const sticky = new MatrixEvent({ + type: "m.rtc.member", + sender: "@a:example.org", + event_id: "$s1", + room_id: ROOM_ID, + origin_server_ts: 1, + content: { slot_id: "m.call#ROOM" }, + }); + room.emit(RoomStickyEventsEvent.Update, [sticky], [], []); + await vi.waitFor(() => { + expect(roomSink.emit).toHaveBeenCalledTimes(1); + const [json, origin] = roomSink.emit.mock.calls[0] as unknown as [ + string, + FfiEventOrigin, + ]; + expect(JSON.parse(json)).toMatchObject({ + type: "m.rtc.member", + event_id: "$s1", + content: { slot_id: "m.call#ROOM" }, + }); + // not encrypted on this fake: the origin says so honestly + expect(FfiEventOrigin.Cleartext.instanceOf(origin)).toBe(true); + }); + + const slot = new MatrixEvent({ + type: "m.rtc.slot", + sender: "@admin:example.org", + event_id: "$slot", + room_id: ROOM_ID, + state_key: "m.call#ROOM", + origin_server_ts: 2, + content: { status: "open" }, + }); + client.emit(RoomStateEvent.Events, slot, null, null); + expect(stateSink.emit).toHaveBeenCalledTimes(1); + expect( + JSON.parse( + (stateSink.emit.mock.calls[0] as unknown as [string[]])[0][0], + ), + ).toMatchObject({ type: "m.rtc.slot", state_key: "m.call#ROOM" }); + + // another room's state is not ours + client.emit( + RoomStateEvent.Events, + new MatrixEvent({ ...slot.event, room_id: "!other:example.org" }), + null, + null, + ); + expect(stateSink.emit).toHaveBeenCalledTimes(1); + }); + + it("reports to-device messages with their Olm sender device and cross-signing verdict", async () => { + const { client, driver } = fullClient(); + const toDevice = sink(); + driver.subscribeToDeviceEvents(toDevice as unknown as ToDeviceSinkLike); + client.emit(ClientEvent.ReceivedToDeviceMessage, { + message: { + type: "m.rtc.encryption_key", + sender: "@a:example.org", + content: { member_id: "m-a" }, + }, + encryptionInfo: { + sender: "@a:example.org", + senderDevice: "ADEV", + senderCurve25519KeyBase64: "k", + }, + }); + await vi.waitFor(() => expect(toDevice.emit).toHaveBeenCalledTimes(1)); + const [type, sender, json, origin, crossSigned] = toDevice.emit.mock + .calls[0] as unknown as [ + string, + string, + string, + FfiEventOrigin, + boolean, + ]; + expect(type).toBe("m.rtc.encryption_key"); + expect(sender).toBe("@a:example.org"); + expect(JSON.parse(json)).toEqual({ member_id: "m-a" }); + expect(senderDeviceOf(origin)).toBe("ADEV"); + expect(crossSigned).toBe(true); + }); + + it("reports homeserver connectivity from the sync state", () => { + const { client, driver } = fullClient(); + expect(driver.isHomeserverConnected()).toBe(true); + const connectivity = sink(); + driver.subscribeConnectivity( + connectivity as unknown as ConnectivitySinkLike, + ); + client.getSyncState.mockReturnValue(SyncState.Error); + client.emit(ClientEvent.Sync, SyncState.Error, SyncState.Syncing); + expect(connectivity.emit).toHaveBeenCalledWith(false); + expect(driver.isHomeserverConnected()).toBe(false); + client.getSyncState.mockReturnValue(SyncState.Syncing); + client.emit(ClientEvent.Sync, SyncState.Syncing, SyncState.Error); + expect(connectivity.emit).toHaveBeenLastCalledWith(true); + }); + }); + + describe("over a RoomWidgetClient", () => { + it("listens for the legacy to-device event and reports the claimed device", async () => { + const { client, driver } = widgetClient(); + const toDevice = sink(); + driver.subscribeToDeviceEvents(toDevice as unknown as ToDeviceSinkLike); + const event = new MatrixEvent({ + type: "io.element.call.encryption_keys", + sender: "@a:example.org", + content: { member: { id: "m-a", claimed_device_id: "ADEV" } }, + }); + event.makeEncrypted("m.room.encrypted", {}, "", ""); + client.emit(ClientEvent.ToDeviceEvent, event); + await vi.waitFor(() => expect(toDevice.emit).toHaveBeenCalledTimes(1)); + const [, , , origin, crossSigned] = toDevice.emit.mock + .calls[0] as unknown as [ + string, + string, + string, + FfiEventOrigin, + boolean | undefined, + ]; + expect(senderDeviceOf(origin)).toBe("ADEV"); + expect(crossSigned).toBeUndefined(); + }); + + it("treats member events in an encrypted room as encrypted by the claimed device", async () => { + const { room, driver } = widgetClient(); + const roomSink = sink(); + driver.subscribeRoomEvents(roomSink as unknown as RoomEventSinkLike); + room.emit( + RoomStickyEventsEvent.Update, + [ + new MatrixEvent({ + type: "m.rtc.member", + sender: "@a:example.org", + event_id: "$s1", + room_id: ROOM_ID, + origin_server_ts: 1, + content: { slot_id: "m.call#ROOM", member: { device_id: "ADEV" } }, + }), + ], + [], + [], + ); + await vi.waitFor(() => expect(roomSink.emit).toHaveBeenCalledTimes(1)); + const origin = ( + roomSink.emit.mock.calls[0] as unknown as [string, FfiEventOrigin] + )[1]; + expect(senderDeviceOf(origin)).toBe("ADEV"); + }); + }); +}); + +function fullClient(): { + client: FakeClient; + room: FakeRoom; + driver: JsSdkRtcMatrixDriver; +} { + const client = fakeClient(false); + const room = fakeRoom(); + return { + client, + room, + driver: new JsSdkRtcMatrixDriver(asClient(client), asRoom(room)), + }; +} + +function widgetClient(): { + client: FakeClient; + room: FakeRoom; + driver: JsSdkRtcMatrixDriver; +} { + const client = fakeClient(true); + const room = fakeRoom(); + return { + client, + room, + driver: new JsSdkRtcMatrixDriver(asClient(client), asRoom(room)), + }; +} + +type SinkEmit = ReturnType boolean>>; + +function sink(): { emit: SinkEmit } { + return { emit: vi.fn<(...args: unknown[]) => boolean>(() => true) }; +} + +/** The sender device an origin carries, if it is an encrypted one. */ +function senderDeviceOf(origin: FfiEventOrigin): string | undefined { + return FfiEventOrigin.Encrypted.instanceOf(origin) + ? origin.inner.senderDeviceId + : undefined; +} diff --git a/src/driver/jsSdk/JsSdkRtcMatrixDriver.ts b/src/driver/jsSdk/JsSdkRtcMatrixDriver.ts new file mode 100644 index 000000000..c0c4da1e9 --- /dev/null +++ b/src/driver/jsSdk/JsSdkRtcMatrixDriver.ts @@ -0,0 +1,630 @@ +/* +Copyright 2026 Element Creations Ltd. + +SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial +Please see LICENSE in the repository root for full details. +*/ + +/** + * An {@link RtcMatrixDriver} over a matrix-js-sdk client: the crate's + * MatrixRTC seam, nothing else. The standalone app, the widget and the SDK + * build hand this to Element Call, and a host that already runs matrix-js-sdk + * can use it as it is. + * + * It serves two kinds of client. A full `MatrixClient` syncs, decrypts and + * has an access token of its own. A `RoomWidgetClient` is a shell over the + * widget API: it never sees ciphertext (its host decrypts), has no crypto + * backend and no token, only emits the legacy to-device event, and answers + * transport discovery over the widget API. Every place the two differ is + * marked "widget". + * + * Adapted from the crate's `web-test-app/src/jsSdkDriver.ts`. + */ + +import { + ClientEvent, + type IOpenIDToken, + type MatrixClient, + type MatrixEvent, + MatrixError, + type ReceivedToDeviceMessage, + type Room, + RoomEvent, + RoomStateEvent, + RoomStickyEventsEvent, + RoomWidgetClient, + SyncState, + UnsupportedDelayedEventsEndpointError, + UnsupportedStickyEventsEndpointError, + UpdateDelayedEventAction, + parseErrorResponse, +} from "matrix-js-sdk"; +import { type Transport } from "matrix-js-sdk/lib/matrixrtc"; +import { logger as rootLogger, type Logger } from "matrix-js-sdk/lib/logger"; + +import { + FfiEventOrigin, + RtcError, + type ConnectivitySinkLike, + type FfiLivekitToken, + type FfiLivekitTokenRequest, + type FfiRtcTransport, + type FfiSendEventResponse, + type FfiToDeviceDelivery, + type FfiToDeviceRecipient, + type RoomEventSinkLike, + type StateUpdateSinkLike, + type ToDeviceSinkLike, +} from "../../matrix-rtc-sdk"; +import { doNetworkOperationWithRetry } from "../../utils/matrix"; +import { type RtcMatrixDriver } from "../RtcMatrixDriver"; + +export interface JsSdkRtcMatrixDriverOptions { + logger?: Logger; +} + +export class JsSdkRtcMatrixDriver implements RtcMatrixDriver { + private readonly roomId: string; + private readonly logger: Logger; + /** Widget: the host decrypts for us and there is no crypto backend. */ + private readonly widget: boolean; + private readonly detachers: (() => void)[] = []; + /** curve25519 sender key → device id, per megolm-attributed sender. */ + private readonly senderDeviceCache = new Map(); + + public constructor( + private readonly client: MatrixClient, + private readonly room: Room, + options: JsSdkRtcMatrixDriverOptions = {}, + ) { + this.roomId = room.roomId; + this.widget = client instanceof RoomWidgetClient; + this.logger = (options.logger ?? rootLogger).getChild( + `[JsSdkRtcMatrixDriver ${room.roomId}]`, + ); + } + + /** Unhooks every client listener. The crate's sinks stop being fed. */ + public detach(): void { + for (const detach of this.detachers.splice(0)) detach(); + } + + // --- outbound -------------------------------------------------------------- + + public async sendStickyEvent( + roomId: string, + eventType: string, + contentJson: string, + durationMs: bigint, + ): Promise { + return guard(async () => { + const res = await this.client._unstable_sendStickyEvent( + roomId, + Number(durationMs), + null, + eventType as never, + JSON.parse(contentJson) as never, + ); + return { eventId: res.event_id, delayId: undefined }; + }); + } + + public async sendStateEvent( + roomId: string, + eventType: string, + stateKey: string, + contentJson: string, + ): Promise { + return guard(async () => { + const res = await this.client.sendStateEvent( + roomId, + eventType as never, + JSON.parse(contentJson) as never, + stateKey, + ); + return { eventId: res.event_id, delayId: undefined }; + }); + } + + public async sendDelayedEvent( + roomId: string, + eventType: string, + contentJson: string, + delayMs: bigint, + stickyDurationMs: bigint | undefined, + ): Promise { + return guard(async () => { + const content = JSON.parse(contentJson) as never; + const res = + stickyDurationMs === undefined + ? await this.client._unstable_sendDelayedEvent( + roomId, + { delay: Number(delayMs) }, + null, + eventType as never, + content, + ) + : await this.client._unstable_sendStickyDelayedEvent( + roomId, + Number(stickyDurationMs), + { delay: Number(delayMs) }, + null, + eventType as never, + content, + ); + return res.delay_id; + }); + } + + public async sendDelayedStateEvent( + roomId: string, + eventType: string, + stateKey: string, + contentJson: string, + delayMs: bigint, + ): Promise { + return guard(async () => { + const res = await this.client._unstable_sendDelayedStateEvent( + roomId, + { delay: Number(delayMs) }, + eventType as never, + JSON.parse(contentJson) as never, + stateKey, + ); + return res.delay_id; + }); + } + + public async restartDelayedEvent( + _roomId: string, + delayId: string, + ): Promise { + await guard(async () => + this.client._unstable_updateDelayedEvent( + delayId, + UpdateDelayedEventAction.Restart, + ), + ); + } + + public async cancelDelayedEvent( + _roomId: string, + delayId: string, + ): Promise { + await guard(async () => + this.client._unstable_updateDelayedEvent( + delayId, + UpdateDelayedEventAction.Cancel, + ), + ); + } + + /** + * MSC4195, the way Element Call has always done it: the MatrixRTC + * authorisation service takes over the delayed leave when asked for a token + * with `delay_id`, `delay_timeout` and the homeserver it should restart it + * at. The token in the answer is discarded. (Interim: plan item C5 moves + * the choice of route into the crate and leaves only primitives here.) + */ + public async delegateLivekitDelayedLeave( + roomId: string, + slotId: string, + memberJson: string, + delayId: string, + livekitServiceUrl: string | undefined, + delayMs: bigint, + ): Promise { + if (livekitServiceUrl === undefined) + throw new RtcError.Unsupported( + "A receive-only member has no transport to delegate to", + ); + await guard(async () => { + const member = JSON.parse(memberJson) as MemberClaims; + const delegation = { + delay_id: delayId, + delay_timeout: Number(delayMs), + delay_cs_api_url: this.client.baseUrl, + }; + await this.requestToken( + livekitServiceUrl, + roomId, + slotId, + member, + false, + delegation, + ); + }); + } + + public async sendToDevice( + recipients: FfiToDeviceRecipient[], + eventType: string, + contentJson: string, + ): Promise { + return guard(async () => { + // Olm-encrypted, per specific device — never `*`. On a widget client + // this asks the host to encrypt; the plain `sendToDevice` there would + // go out in clear. + await this.client.encryptAndSendToDevice( + eventType, + recipients, + JSON.parse(contentJson) as Record, + ); + return recipients.map((recipient) => ({ recipient, error: undefined })); + }); + } + + public async getRtcTransports(): Promise { + return guard(async () => { + // The homeserver endpoint (MSC4143), or the widget host's answer to + // the same question (MSC4515) — the client knows which. + const transports = await doNetworkOperationWithRetry(async () => + this.client._unstable_getRTCTransports(), + ); + return transports.map(({ type, ...properties }: Transport) => ({ + transportType: String(type), + propertiesJson: JSON.stringify(properties), + })); + }); + } + + public async getLivekitToken( + request: FfiLivekitTokenRequest, + ): Promise { + return guard(async () => { + const token = await this.requestToken( + request.url, + request.roomId, + request.slotId, + JSON.parse(request.memberJson) as MemberClaims, + request.legacySfuGet, + ); + return { jwt: token.jwt, url: token.url }; + }); + } + + private async requestToken( + serviceUrl: string, + roomId: string, + slotId: string, + member: MemberClaims, + legacySfuGet: boolean, + delegation: Record = {}, + ): Promise<{ jwt: string; url?: string }> { + let openIdToken: IOpenIDToken; + try { + openIdToken = await doNetworkOperationWithRetry(async () => + this.client.getOpenIdToken(), + ); + } catch (e) { + throw new RtcError.Http(`Could not get an OpenID token: ${String(e)}`); + } + const base = serviceUrl.replace(/\/$/, ""); + const [endpoint, body] = legacySfuGet + ? [ + `${base}/sfu/get`, + { + // The legacy endpoint derives the LiveKit room alias from the + // Matrix room id alone. + room: roomId, + openid_token: openIdToken, + device_id: member.claimed_device_id, + ...delegation, + }, + ] + : [ + `${base}/get_token`, + { + room_id: roomId, + slot_id: slotId, + openid_token: openIdToken, + member, + ...delegation, + }, + ]; + const response = await doNetworkOperationWithRetry(async () => + fetch(endpoint, { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify(body), + }), + ); + if (!response.ok) { + const text = await response.text(); + if (response.status === 404) + throw new RtcError.Unsupported(`${endpoint}: ${response.status}`); + throw parseErrorResponse(response, text); + } + return (await response.json()) as { jwt: string; url?: string }; + } + + // --- reads (the crate's session seed) --------------------------------------- + + public async readEvents( + eventType: string, + _stateKey: string | undefined, + limit: number, + ): Promise { + const out: string[] = []; + for (const event of this.room._unstable_getStickyEvents()) { + await this.client.decryptEventIfNeeded(event); + if (event.getType() !== eventType) continue; + out.push(JSON.stringify(rawEvent(event))); + if (out.length >= limit) break; + } + return out; + } + + public async readState( + eventType: string, + stateKey: string | undefined, + ): Promise { + const events = + stateKey === undefined + ? this.room.currentState.getStateEvents(eventType) + : [this.room.currentState.getStateEvents(eventType, stateKey)].filter( + (e): e is MatrixEvent => Boolean(e), + ); + return Promise.resolve( + events.map((event) => JSON.stringify(rawEvent(event))), + ); + } + + // --- inbound sinks ---------------------------------------------------------- + + public subscribeRoomEvents(sink: RoomEventSinkLike): void { + const emit = async (event: MatrixEvent): Promise => { + await this.client.decryptEventIfNeeded(event); + if (event.isDecryptionFailure()) { + this.logger.warn(`Event ${event.getId()} failed to decrypt; skipped`); + return; + } + if ( + !sink.emit( + JSON.stringify(rawEvent(event)), + await this.roomEventOrigin(event), + ) + ) + detach(); + }; + // Sticky events come from the room's sticky store: sync delivers them in + // the room's `msc4354_sticky` section, our own included. + const onSticky = ( + added: MatrixEvent[], + updated: { current: MatrixEvent }[], + ): void => { + for (const event of [...added, ...updated.map((u) => u.current)]) + void emit(event); + }; + // Everything else (state events in the timeline) comes from the timeline; + // local echoes and sticky events are skipped there. + const onTimeline = ( + event: MatrixEvent, + room: Room | undefined, + toStartOfTimeline: boolean | undefined, + ): void => { + if (room?.roomId !== this.roomId || toStartOfTimeline) return; + if (event.status !== null || event.unstableStickyInfo !== undefined) + return; + void emit(event); + }; + const detach = (): void => { + this.room.off(RoomStickyEventsEvent.Update, onSticky); + this.client.off(RoomEvent.Timeline, onTimeline); + }; + this.room.on(RoomStickyEventsEvent.Update, onSticky); + this.client.on(RoomEvent.Timeline, onTimeline); + this.detachers.push(detach); + } + + public subscribeStateUpdates(sink: StateUpdateSinkLike): void { + // Client-level listener: the room-level re-emit is unreliable under + // MSC4222 `state_after` churn. + const onState = (event: MatrixEvent): void => { + if (event.getRoomId() !== this.roomId) return; + if (!sink.emit([JSON.stringify(rawEvent(event))])) detach(); + }; + const detach = (): void => { + this.client.off(RoomStateEvent.Events, onState); + }; + this.client.on(RoomStateEvent.Events, onState); + this.detachers.push(detach); + } + + public subscribeToDeviceEvents(sink: ToDeviceSinkLike): void { + if (this.widget) { + // Widget: the legacy event is the only one the widget client emits. + // The host decrypted the message; it says whether it was encrypted but + // not by which device, so the device is the one the content claims. + const onToDevice = (event: MatrixEvent): void => { + const content = event.getContent() as KeyMessageContent; + const origin = event.isEncrypted() + ? new FfiEventOrigin.Encrypted({ + senderDeviceId: claimedKeyDevice(content), + }) + : new FfiEventOrigin.Cleartext(); + if ( + !sink.emit( + event.getType(), + event.getSender() ?? "", + JSON.stringify(content), + origin, + undefined, + ) + ) + detach(); + }; + const detach = (): void => { + this.client.off(ClientEvent.ToDeviceEvent, onToDevice); + }; + this.client.on(ClientEvent.ToDeviceEvent, onToDevice); + this.detachers.push(detach); + return; + } + const onToDevice = (received: ReceivedToDeviceMessage): void => + void handleToDevice(received); + const handleToDevice = async ({ + message, + encryptionInfo, + }: ReceivedToDeviceMessage): Promise => { + const origin = encryptionInfo + ? new FfiEventOrigin.Encrypted({ + senderDeviceId: encryptionInfo.senderDevice, + }) + : new FfiEventOrigin.Cleartext(); + // MSC4153: is the sending device cross-signed by its owner? + let crossSigned: boolean | undefined; + const crypto = this.client.getCrypto(); + if (crypto && encryptionInfo?.senderDevice) { + const status = await crypto.getDeviceVerificationStatus( + encryptionInfo.sender, + encryptionInfo.senderDevice, + ); + crossSigned = status?.signedByOwner ?? false; + } + if ( + !sink.emit( + message.type, + message.sender, + JSON.stringify(message.content ?? {}), + origin, + crossSigned, + ) + ) + detach(); + }; + const detach = (): void => { + this.client.off(ClientEvent.ReceivedToDeviceMessage, onToDevice); + }; + this.client.on(ClientEvent.ReceivedToDeviceMessage, onToDevice); + this.detachers.push(detach); + } + + // --- connectivity ------------------------------------------------------------ + + public isHomeserverConnected(): boolean { + // Widget: the widget client reports Syncing once it has seen an event + // and never anything else, so on a widget this is always true. + return this.client.getSyncState() === SyncState.Syncing; + } + + public subscribeConnectivity(sink: ConnectivitySinkLike): void { + const onSync = (): void => { + if (!sink.emit(this.isHomeserverConnected())) detach(); + }; + const detach = (): void => { + this.client.off(ClientEvent.Sync, onSync); + }; + this.client.on(ClientEvent.Sync, onSync); + this.detachers.push(detach); + } + + private async roomEventOrigin(event: MatrixEvent): Promise { + if (this.widget) { + // Widget: events arrive decrypted with no metadata. In an encrypted + // room they were encrypted, by the device the content claims — the + // same trust matrix-js-sdk's own session extends. + if (event.isState() || !this.room.hasEncryptionStateEvent()) + return new FfiEventOrigin.Cleartext(); + return new FfiEventOrigin.Encrypted({ + senderDeviceId: claimedMemberDevice(event.getContent()), + }); + } + if (!event.isEncrypted()) return new FfiEventOrigin.Cleartext(); + return new FfiEventOrigin.Encrypted({ + senderDeviceId: await this.senderDeviceOf(event), + }); + } + + /** The device that megolm-encrypted `event` (sender key → device list). */ + private async senderDeviceOf( + event: MatrixEvent, + ): Promise { + const senderKey = event.getSenderKey(); + const sender = event.getSender(); + const crypto = this.client.getCrypto(); + if (!senderKey || !sender || !crypto) return undefined; + const cached = this.senderDeviceCache.get(senderKey); + if (cached) return cached; + const devices = await crypto.getUserDeviceInfo([sender], true); + for (const device of devices.get(sender)?.values() ?? []) { + if (device.getIdentityKey() === senderKey) { + this.senderDeviceCache.set(senderKey, device.deviceId); + return device.deviceId; + } + } + return undefined; + } +} + +/** The full (decrypted) event object the crate's dispatch reads. */ +function rawEvent(event: MatrixEvent): Record { + return { + ...(event.event as Record), + type: event.getType(), + content: event.getContent(), + sender: event.getSender(), + event_id: event.getId(), + room_id: event.getRoomId(), + origin_server_ts: event.getTs(), + state_key: event.getStateKey(), + }; +} + +/** MSC4195 member claims, as the crate serialises them. */ +interface MemberClaims { + id: string; + claimed_user_id: string; + claimed_device_id: string; +} + +/** The device a media key message claims to come from, in either dialect. */ +interface KeyMessageContent { + member?: { claimed_device_id?: string }; + device_id?: string; +} + +function claimedKeyDevice(content: KeyMessageContent): string | undefined { + return content.member?.claimed_device_id ?? content.device_id; +} + +/** The device a 2025-dialect membership claims (`member.device_id`). */ +function claimedMemberDevice( + content: Record, +): string | undefined { + const member = content.member as { device_id?: unknown } | undefined; + return typeof member?.device_id === "string" ? member.device_id : undefined; +} + +/** Map js-sdk / HTTP failures onto the error the crate reasons about. */ +function toRtcError(error: unknown): Error { + if (RtcError.instanceOf(error)) return error; + if ( + error instanceof UnsupportedDelayedEventsEndpointError || + error instanceof UnsupportedStickyEventsEndpointError + ) + return new RtcError.Unsupported(String(error)); + if (error instanceof MatrixError) { + if (error.errcode === "M_LIMIT_EXCEEDED") + return new RtcError.RateLimited({ + retryAfterMs: + typeof error.data.retry_after_ms === "number" + ? BigInt(error.data.retry_after_ms) + : undefined, + }); + if (error.httpStatus === 404 || error.errcode === "M_UNRECOGNIZED") + return new RtcError.Unsupported(String(error)); + if (error.httpStatus === 403 || error.errcode === "M_FORBIDDEN") + return new RtcError.Rejected(String(error)); + return new RtcError.Http(String(error)); + } + return new RtcError.Driver(String(error)); +} + +async function guard(f: () => Promise): Promise { + try { + return await f(); + } catch (error) { + throw toRtcError(error); + } +} diff --git a/src/driver/jsSdk/jsSdkTestFakes.ts b/src/driver/jsSdk/jsSdkTestFakes.ts new file mode 100644 index 000000000..4c61a2c0d --- /dev/null +++ b/src/driver/jsSdk/jsSdkTestFakes.ts @@ -0,0 +1,150 @@ +/* +Copyright 2026 Element Creations Ltd. + +SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial +Please see LICENSE in the repository root for full details. +*/ + +// Fakes shared by the js-sdk driver tests. The drivers tell the two client +// kinds apart by prototype, so each fake is created on the real prototype +// and given only the members it needs; EventEmitter sits at the bottom of +// that chain, so `on`/`emit` work. + +import { EventEmitter } from "events"; +import { + MatrixClient, + type Room, + RoomWidgetClient, + SyncState, + User, +} from "matrix-js-sdk"; +import { vi } from "vitest"; + +export const ROOM_ID = "!room:example.org"; +export const ME = "@me:example.org"; +export const MY_DEVICE = "MYDEV"; +export const LK = "https://lk.example.org"; + +export const openIdToken = { + access_token: "openid", + expires_in: 3600, + matrix_server_name: "example.org", + token_type: "Bearer", +}; + +type Fn = ReturnType; + +export interface FakeClient extends EventEmitter { + _unstable_sendStickyEvent: Fn; + _unstable_sendDelayedEvent: Fn; + _unstable_sendStickyDelayedEvent: Fn; + _unstable_sendDelayedStateEvent: Fn; + _unstable_updateDelayedEvent: Fn; + _unstable_getRTCTransports: Fn; + sendStateEvent: Fn; + encryptAndSendToDevice: Fn; + sendEvent: Fn; + redactEvent: Fn; + getSyncState: Fn; + getUser: (userId: string) => User | null; +} + +export interface FakeRoom extends EventEmitter { + name: string; +} + +function clientMembers(widget: boolean): Record { + const user = new User(ME); + user.rawDisplayName = "Me"; + user.avatarUrl = "mxc://example.org/me"; + const verification = { signedByOwner: true }; + return { + baseUrl: "https://hs.example.org", + getUserId: () => ME, + getDeviceId: () => MY_DEVICE, + getAccessToken: () => (widget ? null : "token"), + getCrypto: () => + widget + ? undefined + : { + getVersion: () => "fake 1.0", + getDeviceVerificationStatus: async () => + Promise.resolve(verification), + getUserDeviceInfo: async () => Promise.resolve(new Map()), + }, + getSyncState: vi.fn(() => SyncState.Syncing), + getUser: () => user, + getOpenIdToken: async () => Promise.resolve(openIdToken), + decryptEventIfNeeded: async () => Promise.resolve(), + doesServerSupportUnstableFeature: async () => Promise.resolve(true), + mxcUrlToHttp: (mxc: string) => `https://hs.example.org/media/${mxc}`, + _unstable_sendStickyEvent: vi.fn(async () => + Promise.resolve({ event_id: "$sticky" }), + ), + _unstable_sendDelayedEvent: vi.fn(async () => + Promise.resolve({ delay_id: "delay-plain" }), + ), + _unstable_sendStickyDelayedEvent: vi.fn(async () => + Promise.resolve({ delay_id: "delay-sticky" }), + ), + _unstable_sendDelayedStateEvent: vi.fn(async () => + Promise.resolve({ delay_id: "delay-state" }), + ), + _unstable_updateDelayedEvent: vi.fn(async () => Promise.resolve({})), + _unstable_getRTCTransports: vi.fn(async () => Promise.resolve([])), + sendStateEvent: vi.fn(async () => Promise.resolve({ event_id: "$state" })), + encryptAndSendToDevice: vi.fn(async () => Promise.resolve()), + sendEvent: vi.fn(async () => Promise.resolve({ event_id: "$sent" })), + redactEvent: vi.fn(async () => Promise.resolve({ event_id: "$redaction" })), + }; +} + +export function fakeRoom(): FakeRoom { + const room = new EventEmitter() as FakeRoom; + const alice = { + userId: "@a:example.org", + rawDisplayName: "Alice", + getMxcAvatarUrl: () => "mxc://example.org/alice", + }; + const bob = { + userId: "@b:example.org", + rawDisplayName: undefined, + getMxcAvatarUrl: () => undefined, + }; + Object.assign(room, { + roomId: ROOM_ID, + name: "Standup", + getCanonicalAlias: () => "#standup:example.org", + getMxcAvatarUrl: () => "mxc://example.org/room", + hasEncryptionStateEvent: () => true, + currentState: { + getJoinRule: () => "public", + getStateEvents: () => [], + maySendStateEvent: () => true, + }, + getMembersWithMembership: (membership: string) => + membership === "join" ? [alice] : [bob], + _unstable_getStickyEvents: () => [], + relations: { getChildEventsForEvent: () => undefined }, + }); + return room; +} + +export function fakeClient(widget: boolean): FakeClient { + const client = Object.create( + widget ? RoomWidgetClient.prototype : MatrixClient.prototype, + ) as FakeClient; + Object.assign(client, clientMembers(widget)); + return client; +} + +export const asClient = (client: FakeClient): MatrixClient => + client as unknown as MatrixClient; +export const asRoom = (room: FakeRoom): Room => room as unknown as Room; + +export function jsonResponse(body: unknown): Response { + return new Response(JSON.stringify(body), { + status: 200, + headers: { "Content-Type": "application/json" }, + }); +} diff --git a/src/driver/observe.ts b/src/driver/observe.ts new file mode 100644 index 000000000..55976d516 --- /dev/null +++ b/src/driver/observe.ts @@ -0,0 +1,29 @@ +/* +Copyright 2026 Element Creations Ltd. + +SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial +Please see LICENSE in the repository root for full details. +*/ + +import { Observable } from "rxjs"; + +import { type Behavior } from "../state/Behavior"; +import { type ObservableScope } from "../state/ObservableScope"; +import { type Unsubscribe } from "./ElementCallMatrixClientDriver"; + +/** + * Turns one of a driver's `get` / `subscribe` pairs into a behavior owned by + * `scope`: the current value now, every change until the scope ends. + */ +export function observeDriver( + scope: ObservableScope, + get: () => T, + subscribe: (listener: (value: T) => void) => Unsubscribe, +): Behavior { + return scope.behavior( + new Observable((subscriber) => + subscribe((value) => subscriber.next(value)), + ), + get(), + ); +} diff --git a/src/matrix-rtc-sdk/generated/VERSION b/src/matrix-rtc-sdk/generated/VERSION new file mode 100644 index 000000000..692c326aa --- /dev/null +++ b/src/matrix-rtc-sdk/generated/VERSION @@ -0,0 +1,2 @@ +matrix-rtc (MatrixSdkArchitectureDraft) a095ba7-dirty +built 2026-09-15T16:54:50Z by scripts/sync-matrix-rtc-sdk.sh diff --git a/src/matrix-rtc-sdk/generated/matrix_rtc-ffi.ts b/src/matrix-rtc-sdk/generated/matrix_rtc-ffi.ts new file mode 100644 index 000000000..f71af07bf --- /dev/null +++ b/src/matrix-rtc-sdk/generated/matrix_rtc-ffi.ts @@ -0,0 +1,103 @@ +// This file was autogenerated by some hot garbage in the `uniffi-bindgen-react-native` crate. +// Trust me, you don't want to mess with it! + +/* tslint:disable */ +/* eslint-disable */ +// @ts-nocheck + +// Structs and function types for calling back into Typescript from Rust. +export type UniffiRustFutureContinuationCallback = (data: bigint, pollResult: number) => void; +export type UniffiForeignFutureDroppedCallback = (handle: bigint) => void; +export type UniffiForeignFutureDroppedCallbackStruct = { + handle: bigint; + free: UniffiForeignFutureDroppedCallback; +}; +type UniffiCallbackInterfaceMatrixRtcConnectionsListenerMethod0 = (uniffiHandle: bigint, connections: Uint8Array) => UniffiResult; +type UniffiCallbackInterfaceCloneMatrixRtcConnectionsListener = (handle: bigint) => UniffiResult; +type UniffiCallbackInterfaceFreeMatrixRtcConnectionsListener = (handle: bigint) => void; +export type UniffiVTableCallbackInterfaceMatrixRtcConnectionsListener = { + uniffi_free: UniffiCallbackInterfaceFreeMatrixRtcConnectionsListener; + uniffi_clone: UniffiCallbackInterfaceCloneMatrixRtcConnectionsListener; + on_connections_change: UniffiCallbackInterfaceMatrixRtcConnectionsListenerMethod0; +}; +type UniffiCallbackInterfaceMatrixRtcKeyMapListenerMethod0 = (uniffiHandle: bigint, keyMap: Uint8Array, change: Uint8Array) => UniffiResult; +type UniffiCallbackInterfaceCloneMatrixRtcKeyMapListener = (handle: bigint) => UniffiResult; +type UniffiCallbackInterfaceFreeMatrixRtcKeyMapListener = (handle: bigint) => void; +export type UniffiVTableCallbackInterfaceMatrixRtcKeyMapListener = { + uniffi_free: UniffiCallbackInterfaceFreeMatrixRtcKeyMapListener; + uniffi_clone: UniffiCallbackInterfaceCloneMatrixRtcKeyMapListener; + on_key_map_change: UniffiCallbackInterfaceMatrixRtcKeyMapListenerMethod0; +}; +type UniffiCallbackInterfaceMatrixRtcKeyRejectedListenerMethod0 = (uniffiHandle: bigint, memberId: Uint8Array, reason: Uint8Array) => UniffiResult; +type UniffiCallbackInterfaceCloneMatrixRtcKeyRejectedListener = (handle: bigint) => UniffiResult; +type UniffiCallbackInterfaceFreeMatrixRtcKeyRejectedListener = (handle: bigint) => void; +export type UniffiVTableCallbackInterfaceMatrixRtcKeyRejectedListener = { + uniffi_free: UniffiCallbackInterfaceFreeMatrixRtcKeyRejectedListener; + uniffi_clone: UniffiCallbackInterfaceCloneMatrixRtcKeyRejectedListener; + on_key_rejected: UniffiCallbackInterfaceMatrixRtcKeyRejectedListenerMethod0; +}; +export type UniffiForeignFutureResultRustBuffer = { + return_value: Uint8Array; + call_status: UniffiRustCallStatus; +}; +export type UniffiForeignFutureCompleterustBuffer = (callbackData: bigint, result: UniffiForeignFutureResultRustBuffer) => void; +type UniffiCallbackInterfaceMatrixRtcMatrixDriverCallbackMethod0 = (uniffiHandle: bigint, roomId: Uint8Array, eventType: Uint8Array, contentJson: Uint8Array, durationMs: bigint, uniffiFutureCallback: UniffiForeignFutureCompleterustBuffer, uniffiCallbackData: bigint) => UniffiForeignFutureDroppedCallbackStruct; +type UniffiCallbackInterfaceMatrixRtcMatrixDriverCallbackMethod1 = (uniffiHandle: bigint, roomId: Uint8Array, eventType: Uint8Array, stateKey: Uint8Array, contentJson: Uint8Array, uniffiFutureCallback: UniffiForeignFutureCompleterustBuffer, uniffiCallbackData: bigint) => UniffiForeignFutureDroppedCallbackStruct; +type UniffiCallbackInterfaceMatrixRtcMatrixDriverCallbackMethod2 = (uniffiHandle: bigint, roomId: Uint8Array, eventType: Uint8Array, contentJson: Uint8Array, delayMs: bigint, stickyDurationMs: Uint8Array, uniffiFutureCallback: UniffiForeignFutureCompleterustBuffer, uniffiCallbackData: bigint) => UniffiForeignFutureDroppedCallbackStruct; +type UniffiCallbackInterfaceMatrixRtcMatrixDriverCallbackMethod3 = (uniffiHandle: bigint, roomId: Uint8Array, eventType: Uint8Array, stateKey: Uint8Array, contentJson: Uint8Array, delayMs: bigint, uniffiFutureCallback: UniffiForeignFutureCompleterustBuffer, uniffiCallbackData: bigint) => UniffiForeignFutureDroppedCallbackStruct; +export type UniffiForeignFutureResultVoid = { + call_status: UniffiRustCallStatus; +}; +export type UniffiForeignFutureCompletevoid = (callbackData: bigint, result: UniffiForeignFutureResultVoid) => void; +type UniffiCallbackInterfaceMatrixRtcMatrixDriverCallbackMethod4 = (uniffiHandle: bigint, roomId: Uint8Array, delayId: Uint8Array, uniffiFutureCallback: UniffiForeignFutureCompletevoid, uniffiCallbackData: bigint) => UniffiForeignFutureDroppedCallbackStruct; +type UniffiCallbackInterfaceMatrixRtcMatrixDriverCallbackMethod5 = (uniffiHandle: bigint, roomId: Uint8Array, delayId: Uint8Array, uniffiFutureCallback: UniffiForeignFutureCompletevoid, uniffiCallbackData: bigint) => UniffiForeignFutureDroppedCallbackStruct; +type UniffiCallbackInterfaceMatrixRtcMatrixDriverCallbackMethod6 = (uniffiHandle: bigint, roomId: Uint8Array, slotId: Uint8Array, memberJson: Uint8Array, delayId: Uint8Array, livekitServiceUrl: Uint8Array, delayMs: bigint, uniffiFutureCallback: UniffiForeignFutureCompletevoid, uniffiCallbackData: bigint) => UniffiForeignFutureDroppedCallbackStruct; +type UniffiCallbackInterfaceMatrixRtcMatrixDriverCallbackMethod7 = (uniffiHandle: bigint, recipients: Uint8Array, eventType: Uint8Array, contentJson: Uint8Array, uniffiFutureCallback: UniffiForeignFutureCompleterustBuffer, uniffiCallbackData: bigint) => UniffiForeignFutureDroppedCallbackStruct; +type UniffiCallbackInterfaceMatrixRtcMatrixDriverCallbackMethod8 = (uniffiHandle: bigint, uniffiFutureCallback: UniffiForeignFutureCompleterustBuffer, uniffiCallbackData: bigint) => UniffiForeignFutureDroppedCallbackStruct; +type UniffiCallbackInterfaceMatrixRtcMatrixDriverCallbackMethod9 = (uniffiHandle: bigint, request: Uint8Array, uniffiFutureCallback: UniffiForeignFutureCompleterustBuffer, uniffiCallbackData: bigint) => UniffiForeignFutureDroppedCallbackStruct; +type UniffiCallbackInterfaceMatrixRtcMatrixDriverCallbackMethod10 = (uniffiHandle: bigint, eventType: Uint8Array, stateKey: Uint8Array, limit: number, uniffiFutureCallback: UniffiForeignFutureCompleterustBuffer, uniffiCallbackData: bigint) => UniffiForeignFutureDroppedCallbackStruct; +type UniffiCallbackInterfaceMatrixRtcMatrixDriverCallbackMethod11 = (uniffiHandle: bigint, eventType: Uint8Array, stateKey: Uint8Array, uniffiFutureCallback: UniffiForeignFutureCompleterustBuffer, uniffiCallbackData: bigint) => UniffiForeignFutureDroppedCallbackStruct; +type UniffiCallbackInterfaceMatrixRtcMatrixDriverCallbackMethod12 = (uniffiHandle: bigint, sink: bigint) => UniffiResult; +type UniffiCallbackInterfaceMatrixRtcMatrixDriverCallbackMethod13 = (uniffiHandle: bigint, sink: bigint) => UniffiResult; +type UniffiCallbackInterfaceMatrixRtcMatrixDriverCallbackMethod14 = (uniffiHandle: bigint, sink: bigint) => UniffiResult; +type UniffiCallbackInterfaceMatrixRtcMatrixDriverCallbackMethod15 = (uniffiHandle: bigint) => number; +type UniffiCallbackInterfaceMatrixRtcMatrixDriverCallbackMethod16 = (uniffiHandle: bigint, sink: bigint) => UniffiResult; +type UniffiCallbackInterfaceCloneMatrixRtcMatrixDriverCallback = (handle: bigint) => UniffiResult; +type UniffiCallbackInterfaceFreeMatrixRtcMatrixDriverCallback = (handle: bigint) => void; +export type UniffiVTableCallbackInterfaceMatrixRtcMatrixDriverCallback = { + uniffi_free: UniffiCallbackInterfaceFreeMatrixRtcMatrixDriverCallback; + uniffi_clone: UniffiCallbackInterfaceCloneMatrixRtcMatrixDriverCallback; + send_sticky_event: UniffiCallbackInterfaceMatrixRtcMatrixDriverCallbackMethod0; + send_state_event: UniffiCallbackInterfaceMatrixRtcMatrixDriverCallbackMethod1; + send_delayed_event: UniffiCallbackInterfaceMatrixRtcMatrixDriverCallbackMethod2; + send_delayed_state_event: UniffiCallbackInterfaceMatrixRtcMatrixDriverCallbackMethod3; + restart_delayed_event: UniffiCallbackInterfaceMatrixRtcMatrixDriverCallbackMethod4; + cancel_delayed_event: UniffiCallbackInterfaceMatrixRtcMatrixDriverCallbackMethod5; + delegate_livekit_delayed_leave: UniffiCallbackInterfaceMatrixRtcMatrixDriverCallbackMethod6; + send_to_device: UniffiCallbackInterfaceMatrixRtcMatrixDriverCallbackMethod7; + get_rtc_transports: UniffiCallbackInterfaceMatrixRtcMatrixDriverCallbackMethod8; + get_livekit_token: UniffiCallbackInterfaceMatrixRtcMatrixDriverCallbackMethod9; + read_events: UniffiCallbackInterfaceMatrixRtcMatrixDriverCallbackMethod10; + read_state: UniffiCallbackInterfaceMatrixRtcMatrixDriverCallbackMethod11; + subscribe_room_events: UniffiCallbackInterfaceMatrixRtcMatrixDriverCallbackMethod12; + subscribe_to_device_events: UniffiCallbackInterfaceMatrixRtcMatrixDriverCallbackMethod13; + subscribe_state_updates: UniffiCallbackInterfaceMatrixRtcMatrixDriverCallbackMethod14; + is_homeserver_connected: UniffiCallbackInterfaceMatrixRtcMatrixDriverCallbackMethod15; + subscribe_connectivity: UniffiCallbackInterfaceMatrixRtcMatrixDriverCallbackMethod16; +}; +type UniffiCallbackInterfaceMatrixRtcMembershipsListenerMethod0 = (uniffiHandle: bigint, memberships: Uint8Array) => UniffiResult; +type UniffiCallbackInterfaceCloneMatrixRtcMembershipsListener = (handle: bigint) => UniffiResult; +type UniffiCallbackInterfaceFreeMatrixRtcMembershipsListener = (handle: bigint) => void; +export type UniffiVTableCallbackInterfaceMatrixRtcMembershipsListener = { + uniffi_free: UniffiCallbackInterfaceFreeMatrixRtcMembershipsListener; + uniffi_clone: UniffiCallbackInterfaceCloneMatrixRtcMembershipsListener; + on_memberships_change: UniffiCallbackInterfaceMatrixRtcMembershipsListenerMethod0; +}; +type UniffiCallbackInterfaceMatrixRtcStatusListenerMethod0 = (uniffiHandle: bigint, status: Uint8Array) => UniffiResult; +type UniffiCallbackInterfaceCloneMatrixRtcStatusListener = (handle: bigint) => UniffiResult; +type UniffiCallbackInterfaceFreeMatrixRtcStatusListener = (handle: bigint) => void; +export type UniffiVTableCallbackInterfaceMatrixRtcStatusListener = { + uniffi_free: UniffiCallbackInterfaceFreeMatrixRtcStatusListener; + uniffi_clone: UniffiCallbackInterfaceCloneMatrixRtcStatusListener; + on_status_change: UniffiCallbackInterfaceMatrixRtcStatusListenerMethod0; +}; \ No newline at end of file diff --git a/src/matrix-rtc-sdk/generated/matrix_rtc.ts b/src/matrix-rtc-sdk/generated/matrix_rtc.ts new file mode 100644 index 000000000..7098b51e2 --- /dev/null +++ b/src/matrix-rtc-sdk/generated/matrix_rtc.ts @@ -0,0 +1,8716 @@ +// This file was autogenerated by some hot garbage in the `uniffi-bindgen-react-native` crate. +// Trust me, you don't want to mess with it! +/* tslint:disable */ +/* eslint-disable */ +// @ts-nocheck +import * as wasmBundle from "./wasm-bindgen/index.js"; +import { type UniffiRustFutureContinuationCallback, type UniffiForeignFutureDroppedCallback, type UniffiForeignFutureDroppedCallbackStruct, type UniffiVTableCallbackInterfaceMatrixRtcConnectionsListener, type UniffiVTableCallbackInterfaceMatrixRtcKeyMapListener, type UniffiVTableCallbackInterfaceMatrixRtcKeyRejectedListener, type UniffiForeignFutureResultRustBuffer, type UniffiForeignFutureCompleterustBuffer, type UniffiForeignFutureResultVoid, type UniffiForeignFutureCompletevoid, type UniffiVTableCallbackInterfaceMatrixRtcMatrixDriverCallback, type UniffiVTableCallbackInterfaceMatrixRtcMembershipsListener, type UniffiVTableCallbackInterfaceMatrixRtcStatusListener, +} from "./matrix_rtc-ffi"; +import { type FfiConverter, type UniffiByteArray, type UniffiGcObject, type UniffiHandle, type UniffiObjectFactory, type UniffiReferenceHolder, type UniffiRustCallStatus, AbstractFfiConverterByteArray, Cursor, FfiConverterArray, FfiConverterArrayBuffer, FfiConverterBool, FfiConverterObject, FfiConverterObjectWithCallbacks, FfiConverterOptional, FfiConverterUInt32, FfiConverterUInt64, FfiConverterUInt8, RustBuffer, UniffiAbstractObject, UniffiEnum, UniffiError, UniffiInternalError, UniffiResult, UniffiRustCaller, destructorGuardSymbol, pointerLiteralSymbol, uniffiCreateFfiConverterString, uniffiCreateRecord, uniffiRustCallAsync, uniffiTraitInterfaceCall, uniffiTraitInterfaceCallAsyncWithError, uniffiTypeNameSymbol, variantOrdinalSymbol, +} from "@ubjs/core"; +// wasm1: wrap the wasm-bindgen namespace once so the codegen call sites can +// uniformly reference `nativeModule().rustbuffer_alloc` / `.rustbuffer_free`. +// For wasm1, RustBuffers are plain JS Uint8Arrays — no Rust-side allocation +// is involved, so alloc just hands back a fresh view and free is a no-op. +const _nativeModule = Object.assign({}, wasmBundle, { + rustbuffer_alloc: (n: number): Uint8Array => new Uint8Array(n), + rustbuffer_free: (_: Uint8Array): void => {}, +}); +const nativeModule = () => _nativeModule; +const uniffiCaller = new UniffiRustCaller(() => new wasmBundle.RustCallStatus()); + +const uniffiIsDebug = + // @ts-ignore -- The process global might not be defined + typeof process !== "object" || + // @ts-ignore -- The process global might not be defined + process?.env?.NODE_ENV !== "production" || + false; + +// Public interface members begin here. + +/** + * Static session computation for room-list / header info: values, not + * subscriptions — call it on every room update and populate room_info from + * the snapshot fields. Takes all relevant events in one list (sticky and + * state, many rooms at once — the dispatch groups by room and slot). + * Origins are unknown here, so origin-dependent conditions stay + * unenforced — fine for room-info purposes. + */ +export function computeSessionsFromEvents(eventsJson: Array, compat: FfiElementCallCompat): Array /*throws*/ { + const __rb: Uint8Array = uniffiCaller.rustCallWithError( + /*liftError:*/ FfiConverterTypeRtcError.lift.bind(FfiConverterTypeRtcError), + /*caller:*/ (callStatus) => { + return nativeModule().ubrn_uniffi_matrix_rtc_fn_func_compute_sessions_from_events( + FfiConverterSequenceString.lower(eventsJson, nativeModule().rustbuffer_alloc), + FfiConverterTypeFfiElementCallCompat.lower(compat, nativeModule().rustbuffer_alloc), + callStatus); + }, + /*liftString:*/ FfiConverterString.lift.bind(FfiConverterString), + ); + try { + return FfiConverterSequenceTypeFfiSessionSnapshot.lift(__rb); + } finally { + nativeModule().rustbuffer_free(__rb); + } + } + +/** + * The severity of one impairment, so a host can sort or filter without + * re-deriving the table. (`impairments` already arrives sorted, most severe + * first.) + */ +export function impairmentSeverity(impairment: FfiImpairment): FfiSeverity { + const __rb: Uint8Array = uniffiCaller.rustCall( + /*caller:*/ (callStatus) => { + return nativeModule().ubrn_uniffi_matrix_rtc_fn_func_impairment_severity( + FfiConverterTypeFfiImpairment.lower(impairment, nativeModule().rustbuffer_alloc), + callStatus); + }, + /*liftString:*/ FfiConverterString.lift.bind(FfiConverterString), + ); + try { + return FfiConverterTypeFfiSeverity.lift(__rb); + } finally { + nativeModule().rustbuffer_free(__rb); + } + } + +const stringConverter = (() => { + const encoder = new TextEncoder(); + const decoder = new TextDecoder(); + return { + stringToBytes: (s: string) => encoder.encode(s), + bytesToString: (ab: UniffiByteArray) => decoder.decode(ab), + stringByteLength: (s: string) => encoder.encode(s).byteLength, + writeStringIntoBuffer: (s: string, buf: any, offset: number): number => { + const view = new Uint8Array( + buf.arrayBuffer, + offset, + buf.arrayBuffer.byteLength - offset, + ); + return encoder.encodeInto(s, view).written; + }, + readStringFromBuffer: (buf: any, offset: number, length: number): string => + decoder.decode(new Uint8Array(buf.arrayBuffer, offset, length)), + }; +})(); +const FfiConverterString = uniffiCreateFfiConverterString(stringConverter); + +export type FfiConnectionData = { + /** + * The connection key (`livekit_service_url`) `FfiMembership::connections` + * refers to. + */ + serviceUrl: string, + /** + * The SFU websocket URL to connect to. + */ + wsUrl: string, + jwtToken: string, + /** + * From the JWT's `exp`; `None` when it carries none. A failed re-mint + * keeps the old token (a host may still be connected on it), so check + * this rather than discovering staleness through a failed connect. + */ + expiresAtTs?: bigint +} + +/** + * Generated factory for {@link FfiConnectionData} record objects. + */ +export const FfiConnectionData = (() => { + const defaults = () => ({ + }); + const create = (() => { + return uniffiCreateRecord>(defaults); + })(); + return Object.freeze({ + create, + new: create, + defaults: () => Object.freeze(defaults()) as Partial, + }); +})(); + +const FfiConverterTypeFfiConnectionData = (() => { + type TypeName = FfiConnectionData; + class FFIConverter extends AbstractFfiConverterByteArray { + readFromCursor(c: Cursor): TypeName { + return { + serviceUrl: FfiConverterString.readFromCursor(c), + wsUrl: FfiConverterString.readFromCursor(c), + jwtToken: FfiConverterString.readFromCursor(c), + expiresAtTs: FfiConverterOptionalUInt64.readFromCursor(c) + }; + } + writeIntoCursor(value: TypeName, c: Cursor): void { + FfiConverterString.writeIntoCursor(value.serviceUrl, c); + FfiConverterString.writeIntoCursor(value.wsUrl, c); + FfiConverterString.writeIntoCursor(value.jwtToken, c); + FfiConverterOptionalUInt64.writeIntoCursor(value.expiresAtTs, c); + } + allocationSize(value: TypeName): number { + return FfiConverterString.allocationSize(value.serviceUrl) + + FfiConverterString.allocationSize(value.wsUrl) + + FfiConverterString.allocationSize(value.jwtToken) + + FfiConverterOptionalUInt64.allocationSize(value.expiresAtTs); + + } + }; + return new FFIConverter(); +})(); + +export enum FfiConnectionProblemKind { + /** + * Wanted, never minted — absent from `connections()` entirely. + */ + NoToken, + /** + * Present in `connections()` but its JWT is past `exp`. + */ + TokenExpired +} + +const FfiConverterTypeFfiConnectionProblemKind = (() => { + type TypeName = FfiConnectionProblemKind; + class FFIConverter extends AbstractFfiConverterByteArray { + readFromCursor(c: Cursor): TypeName { + switch (c.readI32()) { + case 1: return FfiConnectionProblemKind.NoToken; + case 2: return FfiConnectionProblemKind.TokenExpired; + default: throw new UniffiInternalError.UnexpectedEnumCase(); + } + } + writeIntoCursor(value: TypeName, c: Cursor): void { + switch (value) { + case FfiConnectionProblemKind.NoToken: return c.writeI32(1); + case FfiConnectionProblemKind.TokenExpired: return c.writeI32(2); + } + } + allocationSize(value: TypeName): number { + return 4; + } + } + return new FFIConverter(); +})(); + +/** + * A connection the session needs that the host cannot currently use. + */ +export type FfiConnectionProblem = { + serviceUrl: string, + /** + * Members whose media is unavailable because of it. + */ + memberIds: Array, + kind: FfiConnectionProblemKind, + lastError: string, + /** + * When the next mint is due; `0` = at the next beat. + */ + retryAtTs: bigint +} + +/** + * Generated factory for {@link FfiConnectionProblem} record objects. + */ +export const FfiConnectionProblem = (() => { + const defaults = () => ({ + }); + const create = (() => { + return uniffiCreateRecord>(defaults); + })(); + return Object.freeze({ + create, + new: create, + defaults: () => Object.freeze(defaults()) as Partial, + }); +})(); + +const FfiConverterTypeFfiConnectionProblem = (() => { + type TypeName = FfiConnectionProblem; + class FFIConverter extends AbstractFfiConverterByteArray { + readFromCursor(c: Cursor): TypeName { + return { + serviceUrl: FfiConverterString.readFromCursor(c), + memberIds: FfiConverterSequenceString.readFromCursor(c), + kind: FfiConverterTypeFfiConnectionProblemKind.readFromCursor(c), + lastError: FfiConverterString.readFromCursor(c), + retryAtTs: FfiConverterUInt64.readFromCursor(c) + }; + } + writeIntoCursor(value: TypeName, c: Cursor): void { + FfiConverterString.writeIntoCursor(value.serviceUrl, c); + FfiConverterSequenceString.writeIntoCursor(value.memberIds, c); + FfiConverterTypeFfiConnectionProblemKind.writeIntoCursor(value.kind, c); + FfiConverterString.writeIntoCursor(value.lastError, c); + FfiConverterUInt64.writeIntoCursor(value.retryAtTs, c); + } + allocationSize(value: TypeName): number { + return FfiConverterString.allocationSize(value.serviceUrl) + + FfiConverterSequenceString.allocationSize(value.memberIds) + + FfiConverterTypeFfiConnectionProblemKind.allocationSize(value.kind) + + FfiConverterString.allocationSize(value.lastError) + + FfiConverterUInt64.allocationSize(value.retryAtTs); + + } + }; + return new FFIConverter(); +})(); + +export enum FfiDeviceAttribution { + Verified, + Claimed, + Unknown +} + +const FfiConverterTypeFfiDeviceAttribution = (() => { + type TypeName = FfiDeviceAttribution; + class FFIConverter extends AbstractFfiConverterByteArray { + readFromCursor(c: Cursor): TypeName { + switch (c.readI32()) { + case 1: return FfiDeviceAttribution.Verified; + case 2: return FfiDeviceAttribution.Claimed; + case 3: return FfiDeviceAttribution.Unknown; + default: throw new UniffiInternalError.UnexpectedEnumCase(); + } + } + writeIntoCursor(value: TypeName, c: Cursor): void { + switch (value) { + case FfiDeviceAttribution.Verified: return c.writeI32(1); + case FfiDeviceAttribution.Claimed: return c.writeI32(2); + case FfiDeviceAttribution.Unknown: return c.writeI32(3); + } + } + allocationSize(value: TypeName): number { + return 4; + } + } + return new FFIConverter(); +})(); + +export type FfiRtcTransport = { + transportType: string, + /** + * Type-specific fields as a JSON string (LiveKit: `livekit_service_url`). + */ + propertiesJson: string +} + +/** + * Generated factory for {@link FfiRtcTransport} record objects. + */ +export const FfiRtcTransport = (() => { + const defaults = () => ({ + }); + const create = (() => { + return uniffiCreateRecord>(defaults); + })(); + return Object.freeze({ + create, + new: create, + defaults: () => Object.freeze(defaults()) as Partial, + }); +})(); + +const FfiConverterTypeFfiRtcTransport = (() => { + type TypeName = FfiRtcTransport; + class FFIConverter extends AbstractFfiConverterByteArray { + readFromCursor(c: Cursor): TypeName { + return { + transportType: FfiConverterString.readFromCursor(c), + propertiesJson: FfiConverterString.readFromCursor(c) + }; + } + writeIntoCursor(value: TypeName, c: Cursor): void { + FfiConverterString.writeIntoCursor(value.transportType, c); + FfiConverterString.writeIntoCursor(value.propertiesJson, c); + } + allocationSize(value: TypeName): number { + return FfiConverterString.allocationSize(value.transportType) + + FfiConverterString.allocationSize(value.propertiesJson); + + } + }; + return new FFIConverter(); +})(); + +export type FfiMember = { + memberId: string, + userId: string, + deviceId?: string, + deviceAttribution: FfiDeviceAttribution, + /** + * `origin_server_ts` of the event that started this participation, where + * the dialect needs it to tell joins apart (MSC3401 compat). + */ + membershipTs?: bigint, + /** + * From the room's `m.room.member` state for this user, kept current by + * the session: a rename shows up as a memberships change. + */ + displayName?: string, + avatarUrl?: string, + /** + * The membership event this entry was projected from — the *current* + * one, so it changes on every re-send. Relate application events + * (reactions, hand raises) to it. `None` for a member without an event + * yet (our own entry before the echo). + */ + eventId?: string, + intent?: string, + applicationType?: string, + /** + * The transports this member publishes on. + */ + publishedTransports: Array, + canSubscribe: Array +} + +/** + * Generated factory for {@link FfiMember} record objects. + */ +export const FfiMember = (() => { + const defaults = () => ({ + }); + const create = (() => { + return uniffiCreateRecord>(defaults); + })(); + return Object.freeze({ + create, + new: create, + defaults: () => Object.freeze(defaults()) as Partial, + }); +})(); + +const FfiConverterTypeFfiMember = (() => { + type TypeName = FfiMember; + class FFIConverter extends AbstractFfiConverterByteArray { + readFromCursor(c: Cursor): TypeName { + return { + memberId: FfiConverterString.readFromCursor(c), + userId: FfiConverterString.readFromCursor(c), + deviceId: FfiConverterOptionalString.readFromCursor(c), + deviceAttribution: FfiConverterTypeFfiDeviceAttribution.readFromCursor(c), + membershipTs: FfiConverterOptionalUInt64.readFromCursor(c), + displayName: FfiConverterOptionalString.readFromCursor(c), + avatarUrl: FfiConverterOptionalString.readFromCursor(c), + eventId: FfiConverterOptionalString.readFromCursor(c), + intent: FfiConverterOptionalString.readFromCursor(c), + applicationType: FfiConverterOptionalString.readFromCursor(c), + publishedTransports: FfiConverterSequenceTypeFfiRtcTransport.readFromCursor(c), + canSubscribe: FfiConverterSequenceString.readFromCursor(c) + }; + } + writeIntoCursor(value: TypeName, c: Cursor): void { + FfiConverterString.writeIntoCursor(value.memberId, c); + FfiConverterString.writeIntoCursor(value.userId, c); + FfiConverterOptionalString.writeIntoCursor(value.deviceId, c); + FfiConverterTypeFfiDeviceAttribution.writeIntoCursor(value.deviceAttribution, c); + FfiConverterOptionalUInt64.writeIntoCursor(value.membershipTs, c); + FfiConverterOptionalString.writeIntoCursor(value.displayName, c); + FfiConverterOptionalString.writeIntoCursor(value.avatarUrl, c); + FfiConverterOptionalString.writeIntoCursor(value.eventId, c); + FfiConverterOptionalString.writeIntoCursor(value.intent, c); + FfiConverterOptionalString.writeIntoCursor(value.applicationType, c); + FfiConverterSequenceTypeFfiRtcTransport.writeIntoCursor(value.publishedTransports, c); + FfiConverterSequenceString.writeIntoCursor(value.canSubscribe, c); + } + allocationSize(value: TypeName): number { + return FfiConverterString.allocationSize(value.memberId) + + FfiConverterString.allocationSize(value.userId) + + FfiConverterOptionalString.allocationSize(value.deviceId) + + FfiConverterTypeFfiDeviceAttribution.allocationSize(value.deviceAttribution) + + FfiConverterOptionalUInt64.allocationSize(value.membershipTs) + + FfiConverterOptionalString.allocationSize(value.displayName) + + FfiConverterOptionalString.allocationSize(value.avatarUrl) + + FfiConverterOptionalString.allocationSize(value.eventId) + + FfiConverterOptionalString.allocationSize(value.intent) + + FfiConverterOptionalString.allocationSize(value.applicationType) + + FfiConverterSequenceTypeFfiRtcTransport.allocationSize(value.publishedTransports) + + FfiConverterSequenceString.allocationSize(value.canSubscribe); + + } + }; + return new FFIConverter(); +})(); + +export type FfiConnectionWithMembers = { + connection: FfiConnectionData, + members: Array +} + +/** + * Generated factory for {@link FfiConnectionWithMembers} record objects. + */ +export const FfiConnectionWithMembers = (() => { + const defaults = () => ({ + }); + const create = (() => { + return uniffiCreateRecord>(defaults); + })(); + return Object.freeze({ + create, + new: create, + defaults: () => Object.freeze(defaults()) as Partial, + }); +})(); + +const FfiConverterTypeFfiConnectionWithMembers = (() => { + type TypeName = FfiConnectionWithMembers; + class FFIConverter extends AbstractFfiConverterByteArray { + readFromCursor(c: Cursor): TypeName { + return { + connection: FfiConverterTypeFfiConnectionData.readFromCursor(c), + members: FfiConverterSequenceTypeFfiMember.readFromCursor(c) + }; + } + writeIntoCursor(value: TypeName, c: Cursor): void { + FfiConverterTypeFfiConnectionData.writeIntoCursor(value.connection, c); + FfiConverterSequenceTypeFfiMember.writeIntoCursor(value.members, c); + } + allocationSize(value: TypeName): number { + return FfiConverterTypeFfiConnectionData.allocationSize(value.connection) + + FfiConverterSequenceTypeFfiMember.allocationSize(value.members); + + } + }; + return new FFIConverter(); +})(); + +export enum FfiJoinExclusionReason { + SlotClosed, + UnencryptedInEncryptedRoom, + SenderNotInRoom, + Expired +} + +const FfiConverterTypeFfiJoinExclusionReason = (() => { + type TypeName = FfiJoinExclusionReason; + class FFIConverter extends AbstractFfiConverterByteArray { + readFromCursor(c: Cursor): TypeName { + switch (c.readI32()) { + case 1: return FfiJoinExclusionReason.SlotClosed; + case 2: return FfiJoinExclusionReason.UnencryptedInEncryptedRoom; + case 3: return FfiJoinExclusionReason.SenderNotInRoom; + case 4: return FfiJoinExclusionReason.Expired; + default: throw new UniffiInternalError.UnexpectedEnumCase(); + } + } + writeIntoCursor(value: TypeName, c: Cursor): void { + switch (value) { + case FfiJoinExclusionReason.SlotClosed: return c.writeI32(1); + case FfiJoinExclusionReason.UnencryptedInEncryptedRoom: return c.writeI32(2); + case FfiJoinExclusionReason.SenderNotInRoom: return c.writeI32(3); + case FfiJoinExclusionReason.Expired: return c.writeI32(4); + } + } + allocationSize(value: TypeName): number { + return 4; + } + } + return new FFIConverter(); +})(); + +export type FfiExcludedCandidate = { + member: FfiMember, + reason: FfiJoinExclusionReason +} + +/** + * Generated factory for {@link FfiExcludedCandidate} record objects. + */ +export const FfiExcludedCandidate = (() => { + const defaults = () => ({ + }); + const create = (() => { + return uniffiCreateRecord>(defaults); + })(); + return Object.freeze({ + create, + new: create, + defaults: () => Object.freeze(defaults()) as Partial, + }); +})(); + +const FfiConverterTypeFfiExcludedCandidate = (() => { + type TypeName = FfiExcludedCandidate; + class FFIConverter extends AbstractFfiConverterByteArray { + readFromCursor(c: Cursor): TypeName { + return { + member: FfiConverterTypeFfiMember.readFromCursor(c), + reason: FfiConverterTypeFfiJoinExclusionReason.readFromCursor(c) + }; + } + writeIntoCursor(value: TypeName, c: Cursor): void { + FfiConverterTypeFfiMember.writeIntoCursor(value.member, c); + FfiConverterTypeFfiJoinExclusionReason.writeIntoCursor(value.reason, c); + } + allocationSize(value: TypeName): number { + return FfiConverterTypeFfiMember.allocationSize(value.member) + + FfiConverterTypeFfiJoinExclusionReason.allocationSize(value.reason); + + } + }; + return new FFIConverter(); +})(); + +export type FfiJoinParams = { + applicationType: string, + /** + * `application["m.call.intent"]`. + */ + intent?: string, + stickyDurationMs: bigint, + keepAliveTimeoutMs: bigint, + /** + * Lifetime when the homeserver refuses delayed events (default 5 min). + */ + degradedLifetimeMs?: bigint, + delegateDelayedLeave: boolean +} + +/** + * Generated factory for {@link FfiJoinParams} record objects. + */ +export const FfiJoinParams = (() => { + const defaults = () => ({ + }); + const create = (() => { + return uniffiCreateRecord>(defaults); + })(); + return Object.freeze({ + create, + new: create, + defaults: () => Object.freeze(defaults()) as Partial, + }); +})(); + +const FfiConverterTypeFfiJoinParams = (() => { + type TypeName = FfiJoinParams; + class FFIConverter extends AbstractFfiConverterByteArray { + readFromCursor(c: Cursor): TypeName { + return { + applicationType: FfiConverterString.readFromCursor(c), + intent: FfiConverterOptionalString.readFromCursor(c), + stickyDurationMs: FfiConverterUInt64.readFromCursor(c), + keepAliveTimeoutMs: FfiConverterUInt64.readFromCursor(c), + degradedLifetimeMs: FfiConverterOptionalUInt64.readFromCursor(c), + delegateDelayedLeave: FfiConverterBool.readFromCursor(c) + }; + } + writeIntoCursor(value: TypeName, c: Cursor): void { + FfiConverterString.writeIntoCursor(value.applicationType, c); + FfiConverterOptionalString.writeIntoCursor(value.intent, c); + FfiConverterUInt64.writeIntoCursor(value.stickyDurationMs, c); + FfiConverterUInt64.writeIntoCursor(value.keepAliveTimeoutMs, c); + FfiConverterOptionalUInt64.writeIntoCursor(value.degradedLifetimeMs, c); + FfiConverterBool.writeIntoCursor(value.delegateDelayedLeave, c); + } + allocationSize(value: TypeName): number { + return FfiConverterString.allocationSize(value.applicationType) + + FfiConverterOptionalString.allocationSize(value.intent) + + FfiConverterUInt64.allocationSize(value.stickyDurationMs) + + FfiConverterUInt64.allocationSize(value.keepAliveTimeoutMs) + + FfiConverterOptionalUInt64.allocationSize(value.degradedLifetimeMs) + + FfiConverterBool.allocationSize(value.delegateDelayedLeave); + + } + }; + return new FFIConverter(); +})(); + +/** + * Join progress, step by step. + */ +export type FfiJoinProgress = { + hasFetchedTransports: boolean, + hasFetchedInitialMemberList: boolean, + hasCreatedTransportToken: boolean, + hasSentDelayedLeaveEvent: boolean, + hasSentMemberJoinEvent: boolean, + hasDelegatedDelayedEvent: boolean, + hasStartedHeartbeat: boolean +} + +/** + * Generated factory for {@link FfiJoinProgress} record objects. + */ +export const FfiJoinProgress = (() => { + const defaults = () => ({ + }); + const create = (() => { + return uniffiCreateRecord>(defaults); + })(); + return Object.freeze({ + create, + new: create, + defaults: () => Object.freeze(defaults()) as Partial, + }); +})(); + +const FfiConverterTypeFfiJoinProgress = (() => { + type TypeName = FfiJoinProgress; + class FFIConverter extends AbstractFfiConverterByteArray { + readFromCursor(c: Cursor): TypeName { + return { + hasFetchedTransports: FfiConverterBool.readFromCursor(c), + hasFetchedInitialMemberList: FfiConverterBool.readFromCursor(c), + hasCreatedTransportToken: FfiConverterBool.readFromCursor(c), + hasSentDelayedLeaveEvent: FfiConverterBool.readFromCursor(c), + hasSentMemberJoinEvent: FfiConverterBool.readFromCursor(c), + hasDelegatedDelayedEvent: FfiConverterBool.readFromCursor(c), + hasStartedHeartbeat: FfiConverterBool.readFromCursor(c) + }; + } + writeIntoCursor(value: TypeName, c: Cursor): void { + FfiConverterBool.writeIntoCursor(value.hasFetchedTransports, c); + FfiConverterBool.writeIntoCursor(value.hasFetchedInitialMemberList, c); + FfiConverterBool.writeIntoCursor(value.hasCreatedTransportToken, c); + FfiConverterBool.writeIntoCursor(value.hasSentDelayedLeaveEvent, c); + FfiConverterBool.writeIntoCursor(value.hasSentMemberJoinEvent, c); + FfiConverterBool.writeIntoCursor(value.hasDelegatedDelayedEvent, c); + FfiConverterBool.writeIntoCursor(value.hasStartedHeartbeat, c); + } + allocationSize(value: TypeName): number { + return FfiConverterBool.allocationSize(value.hasFetchedTransports) + + FfiConverterBool.allocationSize(value.hasFetchedInitialMemberList) + + FfiConverterBool.allocationSize(value.hasCreatedTransportToken) + + FfiConverterBool.allocationSize(value.hasSentDelayedLeaveEvent) + + FfiConverterBool.allocationSize(value.hasSentMemberJoinEvent) + + FfiConverterBool.allocationSize(value.hasDelegatedDelayedEvent) + + FfiConverterBool.allocationSize(value.hasStartedHeartbeat); + + } + }; + return new FFIConverter(); +})(); + +export type FfiLivekitToken = { + jwt: string, + /** + * The SFU websocket URL from the response, when it returned one. + */ + url?: string +} + +/** + * Generated factory for {@link FfiLivekitToken} record objects. + */ +export const FfiLivekitToken = (() => { + const defaults = () => ({ + }); + const create = (() => { + return uniffiCreateRecord>(defaults); + })(); + return Object.freeze({ + create, + new: create, + defaults: () => Object.freeze(defaults()) as Partial, + }); +})(); + +const FfiConverterTypeFfiLivekitToken = (() => { + type TypeName = FfiLivekitToken; + class FFIConverter extends AbstractFfiConverterByteArray { + readFromCursor(c: Cursor): TypeName { + return { + jwt: FfiConverterString.readFromCursor(c), + url: FfiConverterOptionalString.readFromCursor(c) + }; + } + writeIntoCursor(value: TypeName, c: Cursor): void { + FfiConverterString.writeIntoCursor(value.jwt, c); + FfiConverterOptionalString.writeIntoCursor(value.url, c); + } + allocationSize(value: TypeName): number { + return FfiConverterString.allocationSize(value.jwt) + + FfiConverterOptionalString.allocationSize(value.url); + + } + }; + return new FFIConverter(); +})(); + +/** + * See `driver::LivekitTokenRequest`: the driver fetches the OpenID token + * itself and posts `{ room_id, slot_id, openid_token, member }` to + * `{url}/get_token` — or, with `legacy_sfu_get`, `{ room: room_id, + * openid_token, device_id }` to `{url}/sfu/get`. + */ +export type FfiLivekitTokenRequest = { + url: string, + roomId: string, + slotId: string, + /** + * MSC4195 member claims `{ id, claimed_user_id, claimed_device_id }`. + */ + memberJson: string, + legacySfuGet: boolean +} + +/** + * Generated factory for {@link FfiLivekitTokenRequest} record objects. + */ +export const FfiLivekitTokenRequest = (() => { + const defaults = () => ({ + }); + const create = (() => { + return uniffiCreateRecord>(defaults); + })(); + return Object.freeze({ + create, + new: create, + defaults: () => Object.freeze(defaults()) as Partial, + }); +})(); + +const FfiConverterTypeFfiLivekitTokenRequest = (() => { + type TypeName = FfiLivekitTokenRequest; + class FFIConverter extends AbstractFfiConverterByteArray { + readFromCursor(c: Cursor): TypeName { + return { + url: FfiConverterString.readFromCursor(c), + roomId: FfiConverterString.readFromCursor(c), + slotId: FfiConverterString.readFromCursor(c), + memberJson: FfiConverterString.readFromCursor(c), + legacySfuGet: FfiConverterBool.readFromCursor(c) + }; + } + writeIntoCursor(value: TypeName, c: Cursor): void { + FfiConverterString.writeIntoCursor(value.url, c); + FfiConverterString.writeIntoCursor(value.roomId, c); + FfiConverterString.writeIntoCursor(value.slotId, c); + FfiConverterString.writeIntoCursor(value.memberJson, c); + FfiConverterBool.writeIntoCursor(value.legacySfuGet, c); + } + allocationSize(value: TypeName): number { + return FfiConverterString.allocationSize(value.url) + + FfiConverterString.allocationSize(value.roomId) + + FfiConverterString.allocationSize(value.slotId) + + FfiConverterString.allocationSize(value.memberJson) + + FfiConverterBool.allocationSize(value.legacySfuGet); + + } + }; + return new FFIConverter(); +})(); + +export type FfiMediaKey = { + memberId: string, + key: ArrayBuffer, + index: number, + creationTsMs: bigint +} + +/** + * Generated factory for {@link FfiMediaKey} record objects. + */ +export const FfiMediaKey = (() => { + const defaults = () => ({ + }); + const create = (() => { + return uniffiCreateRecord>(defaults); + })(); + return Object.freeze({ + create, + new: create, + defaults: () => Object.freeze(defaults()) as Partial, + }); +})(); + +const FfiConverterTypeFfiMediaKey = (() => { + type TypeName = FfiMediaKey; + class FFIConverter extends AbstractFfiConverterByteArray { + readFromCursor(c: Cursor): TypeName { + return { + memberId: FfiConverterString.readFromCursor(c), + key: FfiConverterArrayBuffer.readFromCursor(c), + index: FfiConverterUInt8.readFromCursor(c), + creationTsMs: FfiConverterUInt64.readFromCursor(c) + }; + } + writeIntoCursor(value: TypeName, c: Cursor): void { + FfiConverterString.writeIntoCursor(value.memberId, c); + FfiConverterArrayBuffer.writeIntoCursor(value.key, c); + FfiConverterUInt8.writeIntoCursor(value.index, c); + FfiConverterUInt64.writeIntoCursor(value.creationTsMs, c); + } + allocationSize(value: TypeName): number { + return FfiConverterString.allocationSize(value.memberId) + + FfiConverterArrayBuffer.allocationSize(value.key) + + FfiConverterUInt8.allocationSize(value.index) + + FfiConverterUInt64.allocationSize(value.creationTsMs); + + } + }; + return new FFIConverter(); +})(); + +/** + * Why an inbound media key was discarded — the answer to "why can't I hear + * them?", which the crate computes and used to drop on the floor. + */ +export enum FfiKeyRejection { + Cleartext, + UnknownOrigin, + SenderMismatch, + DeviceMismatch, + UnattributableMember, + NotCrossSigned, + WrongRoom, + Outdated, + NotManagingKeys +} + +const FfiConverterTypeFfiKeyRejection = (() => { + type TypeName = FfiKeyRejection; + class FFIConverter extends AbstractFfiConverterByteArray { + readFromCursor(c: Cursor): TypeName { + switch (c.readI32()) { + case 1: return FfiKeyRejection.Cleartext; + case 2: return FfiKeyRejection.UnknownOrigin; + case 3: return FfiKeyRejection.SenderMismatch; + case 4: return FfiKeyRejection.DeviceMismatch; + case 5: return FfiKeyRejection.UnattributableMember; + case 6: return FfiKeyRejection.NotCrossSigned; + case 7: return FfiKeyRejection.WrongRoom; + case 8: return FfiKeyRejection.Outdated; + case 9: return FfiKeyRejection.NotManagingKeys; + default: throw new UniffiInternalError.UnexpectedEnumCase(); + } + } + writeIntoCursor(value: TypeName, c: Cursor): void { + switch (value) { + case FfiKeyRejection.Cleartext: return c.writeI32(1); + case FfiKeyRejection.UnknownOrigin: return c.writeI32(2); + case FfiKeyRejection.SenderMismatch: return c.writeI32(3); + case FfiKeyRejection.DeviceMismatch: return c.writeI32(4); + case FfiKeyRejection.UnattributableMember: return c.writeI32(5); + case FfiKeyRejection.NotCrossSigned: return c.writeI32(6); + case FfiKeyRejection.WrongRoom: return c.writeI32(7); + case FfiKeyRejection.Outdated: return c.writeI32(8); + case FfiKeyRejection.NotManagingKeys: return c.writeI32(9); + } + } + allocationSize(value: TypeName): number { + return 4; + } + } + return new FFIConverter(); +})(); + +/** + * Who can hear whom, for one tile. Two independent booleans: they fail for + * different reasons and a UI renders them in different places. + */ +export type FfiMediaKeyState = { + /** + * They hold our current key: they can decrypt us. + */ + holdsOurKey: boolean, + /** + * We hold theirs: we can decrypt them. + */ + haveTheirKey: boolean, + /** + * Why their most recent key was discarded, while we still lack one. + */ + rejection?: FfiKeyRejection +} + +/** + * Generated factory for {@link FfiMediaKeyState} record objects. + */ +export const FfiMediaKeyState = (() => { + const defaults = () => ({ + }); + const create = (() => { + return uniffiCreateRecord>(defaults); + })(); + return Object.freeze({ + create, + new: create, + defaults: () => Object.freeze(defaults()) as Partial, + }); +})(); + +const FfiConverterTypeFfiMediaKeyState = (() => { + type TypeName = FfiMediaKeyState; + class FFIConverter extends AbstractFfiConverterByteArray { + readFromCursor(c: Cursor): TypeName { + return { + holdsOurKey: FfiConverterBool.readFromCursor(c), + haveTheirKey: FfiConverterBool.readFromCursor(c), + rejection: FfiConverterOptionalTypeFfiKeyRejection.readFromCursor(c) + }; + } + writeIntoCursor(value: TypeName, c: Cursor): void { + FfiConverterBool.writeIntoCursor(value.holdsOurKey, c); + FfiConverterBool.writeIntoCursor(value.haveTheirKey, c); + FfiConverterOptionalTypeFfiKeyRejection.writeIntoCursor(value.rejection, c); + } + allocationSize(value: TypeName): number { + return FfiConverterBool.allocationSize(value.holdsOurKey) + + FfiConverterBool.allocationSize(value.haveTheirKey) + + FfiConverterOptionalTypeFfiKeyRejection.allocationSize(value.rejection); + + } + }; + return new FFIConverter(); +})(); + +export enum FfiMembershipState { + /** + * In the session's joined projection. + */ + Joined, + /** + * Left the session but still holds a not-yet-rotated copy of our media + * key — render as "leaving / may still be listening" until rotation + * settles. + */ + LeftWithKeys +} + +const FfiConverterTypeFfiMembershipState = (() => { + type TypeName = FfiMembershipState; + class FFIConverter extends AbstractFfiConverterByteArray { + readFromCursor(c: Cursor): TypeName { + switch (c.readI32()) { + case 1: return FfiMembershipState.Joined; + case 2: return FfiMembershipState.LeftWithKeys; + default: throw new UniffiInternalError.UnexpectedEnumCase(); + } + } + writeIntoCursor(value: TypeName, c: Cursor): void { + switch (value) { + case FfiMembershipState.Joined: return c.writeI32(1); + case FfiMembershipState.LeftWithKeys: return c.writeI32(2); + } + } + allocationSize(value: TypeName): number { + return 4; + } + } + return new FFIConverter(); +})(); + +/** + * One entry of the membership list — everything needed to render a tile + * and later attach its media from the LK rooms. + */ +export type FfiMembership = { + member: FfiMember, + state: FfiMembershipState, + /** + * `service_url`s (the connection key, `FfiConnectionData::service_url`) + * of the connections this member publishes on — the LK room(s) carrying + * their media. Empty for receive-only members and `LeftWithKeys` + * entries. + */ + connections: Array, + /** + * Participant identity inside those LK rooms (MSC4195 pseudonymous + * hash; `{user}:{device}` in legacy compat mode). + */ + transportIdentity?: string, + /** + * Whether this member and we can hear each other. `None` when the call + * does not manage media keys, for our own tile, and while not joined. + */ + mediaKey?: FfiMediaKeyState +} + +/** + * Generated factory for {@link FfiMembership} record objects. + */ +export const FfiMembership = (() => { + const defaults = () => ({ + }); + const create = (() => { + return uniffiCreateRecord>(defaults); + })(); + return Object.freeze({ + create, + new: create, + defaults: () => Object.freeze(defaults()) as Partial, + }); +})(); + +const FfiConverterTypeFfiMembership = (() => { + type TypeName = FfiMembership; + class FFIConverter extends AbstractFfiConverterByteArray { + readFromCursor(c: Cursor): TypeName { + return { + member: FfiConverterTypeFfiMember.readFromCursor(c), + state: FfiConverterTypeFfiMembershipState.readFromCursor(c), + connections: FfiConverterSequenceString.readFromCursor(c), + transportIdentity: FfiConverterOptionalString.readFromCursor(c), + mediaKey: FfiConverterOptionalTypeFfiMediaKeyState.readFromCursor(c) + }; + } + writeIntoCursor(value: TypeName, c: Cursor): void { + FfiConverterTypeFfiMember.writeIntoCursor(value.member, c); + FfiConverterTypeFfiMembershipState.writeIntoCursor(value.state, c); + FfiConverterSequenceString.writeIntoCursor(value.connections, c); + FfiConverterOptionalString.writeIntoCursor(value.transportIdentity, c); + FfiConverterOptionalTypeFfiMediaKeyState.writeIntoCursor(value.mediaKey, c); + } + allocationSize(value: TypeName): number { + return FfiConverterTypeFfiMember.allocationSize(value.member) + + FfiConverterTypeFfiMembershipState.allocationSize(value.state) + + FfiConverterSequenceString.allocationSize(value.connections) + + FfiConverterOptionalString.allocationSize(value.transportIdentity) + + FfiConverterOptionalTypeFfiMediaKeyState.allocationSize(value.mediaKey); + + } + }; + return new FFIConverter(); +})(); + +/** + * Our sticky membership event on the server (MSC4354). + */ +export type FfiMembershipPublication = { + lifetimeMs: bigint, + lastPublishedTs: bigint, + /** + * `last_published_ts + lifetime_ms` — when the server drops us if no + * refresh lands. + */ + expiresAtTs: bigint, + refreshFailingSinceTs?: bigint, + lastRefreshError?: string +} + +/** + * Generated factory for {@link FfiMembershipPublication} record objects. + */ +export const FfiMembershipPublication = (() => { + const defaults = () => ({ + }); + const create = (() => { + return uniffiCreateRecord>(defaults); + })(); + return Object.freeze({ + create, + new: create, + defaults: () => Object.freeze(defaults()) as Partial, + }); +})(); + +const FfiConverterTypeFfiMembershipPublication = (() => { + type TypeName = FfiMembershipPublication; + class FFIConverter extends AbstractFfiConverterByteArray { + readFromCursor(c: Cursor): TypeName { + return { + lifetimeMs: FfiConverterUInt64.readFromCursor(c), + lastPublishedTs: FfiConverterUInt64.readFromCursor(c), + expiresAtTs: FfiConverterUInt64.readFromCursor(c), + refreshFailingSinceTs: FfiConverterOptionalUInt64.readFromCursor(c), + lastRefreshError: FfiConverterOptionalString.readFromCursor(c) + }; + } + writeIntoCursor(value: TypeName, c: Cursor): void { + FfiConverterUInt64.writeIntoCursor(value.lifetimeMs, c); + FfiConverterUInt64.writeIntoCursor(value.lastPublishedTs, c); + FfiConverterUInt64.writeIntoCursor(value.expiresAtTs, c); + FfiConverterOptionalUInt64.writeIntoCursor(value.refreshFailingSinceTs, c); + FfiConverterOptionalString.writeIntoCursor(value.lastRefreshError, c); + } + allocationSize(value: TypeName): number { + return FfiConverterUInt64.allocationSize(value.lifetimeMs) + + FfiConverterUInt64.allocationSize(value.lastPublishedTs) + + FfiConverterUInt64.allocationSize(value.expiresAtTs) + + FfiConverterOptionalUInt64.allocationSize(value.refreshFailingSinceTs) + + FfiConverterOptionalString.allocationSize(value.lastRefreshError); + + } + }; + return new FFIConverter(); +})(); + +/** + * Pre-2026 Element Call interop, selected per call (session read side + + * own-membership write side). + */ +export enum FfiElementCallCompat { + Off, + StickyEvents, + StateEvents +} + +const FfiConverterTypeFfiElementCallCompat = (() => { + type TypeName = FfiElementCallCompat; + class FFIConverter extends AbstractFfiConverterByteArray { + readFromCursor(c: Cursor): TypeName { + switch (c.readI32()) { + case 1: return FfiElementCallCompat.Off; + case 2: return FfiElementCallCompat.StickyEvents; + case 3: return FfiElementCallCompat.StateEvents; + default: throw new UniffiInternalError.UnexpectedEnumCase(); + } + } + writeIntoCursor(value: TypeName, c: Cursor): void { + switch (value) { + case FfiElementCallCompat.Off: return c.writeI32(1); + case FfiElementCallCompat.StickyEvents: return c.writeI32(2); + case FfiElementCallCompat.StateEvents: return c.writeI32(3); + } + } + allocationSize(value: TypeName): number { + return 4; + } + } + return new FFIConverter(); +})(); + +/** + * Per-manager configuration: the compat dialect plus the encryption knobs a + * host must be able to set (a room without a slot negotiates nothing, so + * the local defaults decide). + */ +export type FfiParticipationConfig = { + compat: FfiElementCallCompat, + /** + * Whether to exchange media keys when the slot prescribes nothing (no + * slot in the room). A slot's negotiated encryption overrides it. + */ + manageMediaKeys: boolean, + /** + * MSC4153: discard media keys from a sending device the host did not + * report as cross-signed by its owner. Hosts that cannot evaluate that + * (or whose peers may be unverified guests) turn it off. + */ + requireCrossSignedSender: boolean, + /** + * Wait this long after sending a rotated key before encrypting with it, + * so slow peers have it before the first frame arrives. + */ + useKeyDelayMs: bigint +} + +/** + * Generated factory for {@link FfiParticipationConfig} record objects. + */ +export const FfiParticipationConfig = (() => { + const defaults = () => ({ + }); + const create = (() => { + return uniffiCreateRecord>(defaults); + })(); + return Object.freeze({ + create, + new: create, + defaults: () => Object.freeze(defaults()) as Partial, + }); +})(); + +const FfiConverterTypeFfiParticipationConfig = (() => { + type TypeName = FfiParticipationConfig; + class FFIConverter extends AbstractFfiConverterByteArray { + readFromCursor(c: Cursor): TypeName { + return { + compat: FfiConverterTypeFfiElementCallCompat.readFromCursor(c), + manageMediaKeys: FfiConverterBool.readFromCursor(c), + requireCrossSignedSender: FfiConverterBool.readFromCursor(c), + useKeyDelayMs: FfiConverterUInt64.readFromCursor(c) + }; + } + writeIntoCursor(value: TypeName, c: Cursor): void { + FfiConverterTypeFfiElementCallCompat.writeIntoCursor(value.compat, c); + FfiConverterBool.writeIntoCursor(value.manageMediaKeys, c); + FfiConverterBool.writeIntoCursor(value.requireCrossSignedSender, c); + FfiConverterUInt64.writeIntoCursor(value.useKeyDelayMs, c); + } + allocationSize(value: TypeName): number { + return FfiConverterTypeFfiElementCallCompat.allocationSize(value.compat) + + FfiConverterBool.allocationSize(value.manageMediaKeys) + + FfiConverterBool.allocationSize(value.requireCrossSignedSender) + + FfiConverterUInt64.allocationSize(value.useKeyDelayMs); + + } + }; + return new FFIConverter(); +})(); + +export type FfiSendEventResponse = { + eventId?: string, + delayId?: string +} + +/** + * Generated factory for {@link FfiSendEventResponse} record objects. + */ +export const FfiSendEventResponse = (() => { + const defaults = () => ({ + }); + const create = (() => { + return uniffiCreateRecord>(defaults); + })(); + return Object.freeze({ + create, + new: create, + defaults: () => Object.freeze(defaults()) as Partial, + }); +})(); + +const FfiConverterTypeFfiSendEventResponse = (() => { + type TypeName = FfiSendEventResponse; + class FFIConverter extends AbstractFfiConverterByteArray { + readFromCursor(c: Cursor): TypeName { + return { + eventId: FfiConverterOptionalString.readFromCursor(c), + delayId: FfiConverterOptionalString.readFromCursor(c) + }; + } + writeIntoCursor(value: TypeName, c: Cursor): void { + FfiConverterOptionalString.writeIntoCursor(value.eventId, c); + FfiConverterOptionalString.writeIntoCursor(value.delayId, c); + } + allocationSize(value: TypeName): number { + return FfiConverterOptionalString.allocationSize(value.eventId) + + FfiConverterOptionalString.allocationSize(value.delayId); + + } + }; + return new FFIConverter(); +})(); + +/** + * One of the room-state / timeline reads the session's seed makes. A read + * that failed leaves its condition *unknown*, which is not the same as the + * condition being absent. + */ +export enum FfiSessionRead { + Slot, + RoomEncryption, + RoomMembers, + MemberEvents +} + +const FfiConverterTypeFfiSessionRead = (() => { + type TypeName = FfiSessionRead; + class FFIConverter extends AbstractFfiConverterByteArray { + readFromCursor(c: Cursor): TypeName { + switch (c.readI32()) { + case 1: return FfiSessionRead.Slot; + case 2: return FfiSessionRead.RoomEncryption; + case 3: return FfiSessionRead.RoomMembers; + case 4: return FfiSessionRead.MemberEvents; + default: throw new UniffiInternalError.UnexpectedEnumCase(); + } + } + writeIntoCursor(value: TypeName, c: Cursor): void { + switch (value) { + case FfiSessionRead.Slot: return c.writeI32(1); + case FfiSessionRead.RoomEncryption: return c.writeI32(2); + case FfiSessionRead.RoomMembers: return c.writeI32(3); + case FfiSessionRead.MemberEvents: return c.writeI32(4); + } + } + allocationSize(value: TypeName): number { + return 4; + } + } + return new FFIConverter(); +})(); + +/** + * One session as a plain value — what [`compute_sessions_from_events`] + * returns. The convenience data the room-list / header / lobby / room_info + * computation needs is precomputed into fields (records carry no methods). + */ +export type FfiSessionSnapshot = { + roomId: string, + slotId: string, + members: Array, + memberCount: number, + isActive: boolean, + /** + * `origin_server_ts` of the earliest joined membership, while active. + */ + startTs?: bigint, + applicationType?: string, + /** + * `None` while no slot state was supplied (condition unenforced). + */ + slotOpen?: boolean, + /** + * The slot-prescribed encryption decision; `None` while unknown. + * + * Read it together with `failed_reads`: `None` with an empty + * `failed_reads` means "this call is not encrypted", `None` with + * `Slot` in it means "we could not find out" — the difference between + * rendering an open padlock and rendering nothing. + */ + encrypted?: boolean, + /** + * `true` once the live session finished seeding (even after read + * failures); always `true` for a statically computed snapshot. + */ + seeded: boolean, + /** + * Seed reads that failed, so an absent value can be told from an + * unknown one. Empty is the healthy case, and an entry disappears once + * a live state update supplies that value. + */ + failedReads: Array, + /** + * Member events that landed but are not in the joined projection, with + * the reason — the load-bearing diagnostics for "why can nobody see + * me?". Find your own entry with `own_member_id()`. + */ + excludedCandidates: Array +} + +/** + * Generated factory for {@link FfiSessionSnapshot} record objects. + */ +export const FfiSessionSnapshot = (() => { + const defaults = () => ({ + }); + const create = (() => { + return uniffiCreateRecord>(defaults); + })(); + return Object.freeze({ + create, + new: create, + defaults: () => Object.freeze(defaults()) as Partial, + }); +})(); + +const FfiConverterTypeFfiSessionSnapshot = (() => { + type TypeName = FfiSessionSnapshot; + class FFIConverter extends AbstractFfiConverterByteArray { + readFromCursor(c: Cursor): TypeName { + return { + roomId: FfiConverterString.readFromCursor(c), + slotId: FfiConverterString.readFromCursor(c), + members: FfiConverterSequenceTypeFfiMember.readFromCursor(c), + memberCount: FfiConverterUInt32.readFromCursor(c), + isActive: FfiConverterBool.readFromCursor(c), + startTs: FfiConverterOptionalUInt64.readFromCursor(c), + applicationType: FfiConverterOptionalString.readFromCursor(c), + slotOpen: FfiConverterOptionalBoolean.readFromCursor(c), + encrypted: FfiConverterOptionalBoolean.readFromCursor(c), + seeded: FfiConverterBool.readFromCursor(c), + failedReads: FfiConverterSequenceTypeFfiSessionRead.readFromCursor(c), + excludedCandidates: FfiConverterSequenceTypeFfiExcludedCandidate.readFromCursor(c) + }; + } + writeIntoCursor(value: TypeName, c: Cursor): void { + FfiConverterString.writeIntoCursor(value.roomId, c); + FfiConverterString.writeIntoCursor(value.slotId, c); + FfiConverterSequenceTypeFfiMember.writeIntoCursor(value.members, c); + FfiConverterUInt32.writeIntoCursor(value.memberCount, c); + FfiConverterBool.writeIntoCursor(value.isActive, c); + FfiConverterOptionalUInt64.writeIntoCursor(value.startTs, c); + FfiConverterOptionalString.writeIntoCursor(value.applicationType, c); + FfiConverterOptionalBoolean.writeIntoCursor(value.slotOpen, c); + FfiConverterOptionalBoolean.writeIntoCursor(value.encrypted, c); + FfiConverterBool.writeIntoCursor(value.seeded, c); + FfiConverterSequenceTypeFfiSessionRead.writeIntoCursor(value.failedReads, c); + FfiConverterSequenceTypeFfiExcludedCandidate.writeIntoCursor(value.excludedCandidates, c); + } + allocationSize(value: TypeName): number { + return FfiConverterString.allocationSize(value.roomId) + + FfiConverterString.allocationSize(value.slotId) + + FfiConverterSequenceTypeFfiMember.allocationSize(value.members) + + FfiConverterUInt32.allocationSize(value.memberCount) + + FfiConverterBool.allocationSize(value.isActive) + + FfiConverterOptionalUInt64.allocationSize(value.startTs) + + FfiConverterOptionalString.allocationSize(value.applicationType) + + FfiConverterOptionalBoolean.allocationSize(value.slotOpen) + + FfiConverterOptionalBoolean.allocationSize(value.encrypted) + + FfiConverterBool.allocationSize(value.seeded) + + FfiConverterSequenceTypeFfiSessionRead.allocationSize(value.failedReads) + + FfiConverterSequenceTypeFfiExcludedCandidate.allocationSize(value.excludedCandidates); + + } + }; + return new FFIConverter(); +})(); + +export type FfiToDeviceRecipient = { + userId: string, + deviceId: string +} + +/** + * Generated factory for {@link FfiToDeviceRecipient} record objects. + */ +export const FfiToDeviceRecipient = (() => { + const defaults = () => ({ + }); + const create = (() => { + return uniffiCreateRecord>(defaults); + })(); + return Object.freeze({ + create, + new: create, + defaults: () => Object.freeze(defaults()) as Partial, + }); +})(); + +const FfiConverterTypeFfiToDeviceRecipient = (() => { + type TypeName = FfiToDeviceRecipient; + class FFIConverter extends AbstractFfiConverterByteArray { + readFromCursor(c: Cursor): TypeName { + return { + userId: FfiConverterString.readFromCursor(c), + deviceId: FfiConverterString.readFromCursor(c) + }; + } + writeIntoCursor(value: TypeName, c: Cursor): void { + FfiConverterString.writeIntoCursor(value.userId, c); + FfiConverterString.writeIntoCursor(value.deviceId, c); + } + allocationSize(value: TypeName): number { + return FfiConverterString.allocationSize(value.userId) + + FfiConverterString.allocationSize(value.deviceId); + + } + }; + return new FFIConverter(); +})(); + +export type FfiToDeviceDelivery = { + recipient: FfiToDeviceRecipient, + error?: string +} + +/** + * Generated factory for {@link FfiToDeviceDelivery} record objects. + */ +export const FfiToDeviceDelivery = (() => { + const defaults = () => ({ + }); + const create = (() => { + return uniffiCreateRecord>(defaults); + })(); + return Object.freeze({ + create, + new: create, + defaults: () => Object.freeze(defaults()) as Partial, + }); +})(); + +const FfiConverterTypeFfiToDeviceDelivery = (() => { + type TypeName = FfiToDeviceDelivery; + class FFIConverter extends AbstractFfiConverterByteArray { + readFromCursor(c: Cursor): TypeName { + return { + recipient: FfiConverterTypeFfiToDeviceRecipient.readFromCursor(c), + error: FfiConverterOptionalString.readFromCursor(c) + }; + } + writeIntoCursor(value: TypeName, c: Cursor): void { + FfiConverterTypeFfiToDeviceRecipient.writeIntoCursor(value.recipient, c); + FfiConverterOptionalString.writeIntoCursor(value.error, c); + } + allocationSize(value: TypeName): number { + return FfiConverterTypeFfiToDeviceRecipient.allocationSize(value.recipient) + + FfiConverterOptionalString.allocationSize(value.error); + + } + }; + return new FFIConverter(); +})(); + +/** + * Which pump stopped, for [`FfiDisconnectCause::ManagerStopped`]. + */ +export enum FfiComponent { + Session, + OwnMembership, + Connections, + Encryption, + Participation +} + +const FfiConverterTypeFfiComponent = (() => { + type TypeName = FfiComponent; + class FFIConverter extends AbstractFfiConverterByteArray { + readFromCursor(c: Cursor): TypeName { + switch (c.readI32()) { + case 1: return FfiComponent.Session; + case 2: return FfiComponent.OwnMembership; + case 3: return FfiComponent.Connections; + case 4: return FfiComponent.Encryption; + case 5: return FfiComponent.Participation; + default: throw new UniffiInternalError.UnexpectedEnumCase(); + } + } + writeIntoCursor(value: TypeName, c: Cursor): void { + switch (value) { + case FfiComponent.Session: return c.writeI32(1); + case FfiComponent.OwnMembership: return c.writeI32(2); + case FfiComponent.Connections: return c.writeI32(3); + case FfiComponent.Encryption: return c.writeI32(4); + case FfiComponent.Participation: return c.writeI32(5); + } + } + allocationSize(value: TypeName): number { + return 4; + } + } + return new FFIConverter(); +})(); + +/** + * What became of the dead man's switch when we left. A failed cancel still + * leaves us out of the call — the delay is itself a leave — but a stray + * delayed event of ours may land afterwards. + */ +export enum FfiDelayedLeaveOutcome { + Cancelled, + MayStillFire +} + +const FfiConverterTypeFfiDelayedLeaveOutcome = (() => { + type TypeName = FfiDelayedLeaveOutcome; + class FFIConverter extends AbstractFfiConverterByteArray { + readFromCursor(c: Cursor): TypeName { + switch (c.readI32()) { + case 1: return FfiDelayedLeaveOutcome.Cancelled; + case 2: return FfiDelayedLeaveOutcome.MayStillFire; + default: throw new UniffiInternalError.UnexpectedEnumCase(); + } + } + writeIntoCursor(value: TypeName, c: Cursor): void { + switch (value) { + case FfiDelayedLeaveOutcome.Cancelled: return c.writeI32(1); + case FfiDelayedLeaveOutcome.MayStillFire: return c.writeI32(2); + } + } + allocationSize(value: TypeName): number { + return 4; + } + } + return new FFIConverter(); +})(); + + +// Enum: FfiJoinError +export enum FfiJoinError_Tags { + AlreadyJoined = "AlreadyJoined", + InvalidParams = "InvalidParams", + SlotClosed = "SlotClosed", + NoTransport = "NoTransport", + TokenRefused = "TokenRefused", + EncryptionSetup = "EncryptionSetup", + Driver = "Driver" +} +/** + * Why a join failed. Typed so a host can decide what to offer next: + * `NoTransport` is a configuration problem, `TokenRefused` may be worth a + * retry. + */ +export const FfiJoinError = (() => { + + type AlreadyJoined__interface = { + tag: FfiJoinError_Tags.AlreadyJoined + }; + class AlreadyJoined_ extends UniffiEnum implements AlreadyJoined__interface { + /** + * @private + * This field is private and should not be used, use `tag` instead. + */ + readonly [uniffiTypeNameSymbol] = "FfiJoinError"; + readonly tag = FfiJoinError_Tags.AlreadyJoined; + constructor() { + super("FfiJoinError", "AlreadyJoined"); + } + + static new(): AlreadyJoined_ { + return new AlreadyJoined_(); + } + + static instanceOf(obj: any): obj is AlreadyJoined_ { + return obj.tag === FfiJoinError_Tags.AlreadyJoined; + } + + } + + type InvalidParams__interface = { + tag: FfiJoinError_Tags.InvalidParams; + inner: +Readonly<{message: string}> + }; + class InvalidParams_ extends UniffiEnum implements InvalidParams__interface { + /** + * @private + * This field is private and should not be used, use `tag` instead. + */ + readonly [uniffiTypeNameSymbol] = "FfiJoinError"; + readonly tag = FfiJoinError_Tags.InvalidParams; + readonly inner: +Readonly<{message: string}>; + constructor( +inner: {message: string }) { + super("FfiJoinError", "InvalidParams"); + + this.inner = Object.freeze(inner); + } + static new( +inner: {message: string }): InvalidParams_ { + return new InvalidParams_(inner); + } + + static instanceOf(obj: any): obj is InvalidParams_ { + return obj.tag === FfiJoinError_Tags.InvalidParams; + } + + } + + type SlotClosed__interface = { + tag: FfiJoinError_Tags.SlotClosed + }; + class SlotClosed_ extends UniffiEnum implements SlotClosed__interface { + /** + * @private + * This field is private and should not be used, use `tag` instead. + */ + readonly [uniffiTypeNameSymbol] = "FfiJoinError"; + readonly tag = FfiJoinError_Tags.SlotClosed; + constructor() { + super("FfiJoinError", "SlotClosed"); + } + + static new(): SlotClosed_ { + return new SlotClosed_(); + } + + static instanceOf(obj: any): obj is SlotClosed_ { + return obj.tag === FfiJoinError_Tags.SlotClosed; + } + + } + + type NoTransport__interface = { + tag: FfiJoinError_Tags.NoTransport; + inner: +Readonly<{message: string}> + }; + class NoTransport_ extends UniffiEnum implements NoTransport__interface { + /** + * @private + * This field is private and should not be used, use `tag` instead. + */ + readonly [uniffiTypeNameSymbol] = "FfiJoinError"; + readonly tag = FfiJoinError_Tags.NoTransport; + readonly inner: +Readonly<{message: string}>; + constructor( +inner: {message: string }) { + super("FfiJoinError", "NoTransport"); + + this.inner = Object.freeze(inner); + } + static new( +inner: {message: string }): NoTransport_ { + return new NoTransport_(inner); + } + + static instanceOf(obj: any): obj is NoTransport_ { + return obj.tag === FfiJoinError_Tags.NoTransport; + } + + } + + type TokenRefused__interface = { + tag: FfiJoinError_Tags.TokenRefused; + inner: +Readonly<{message: string}> + }; + class TokenRefused_ extends UniffiEnum implements TokenRefused__interface { + /** + * @private + * This field is private and should not be used, use `tag` instead. + */ + readonly [uniffiTypeNameSymbol] = "FfiJoinError"; + readonly tag = FfiJoinError_Tags.TokenRefused; + readonly inner: +Readonly<{message: string}>; + constructor( +inner: {message: string }) { + super("FfiJoinError", "TokenRefused"); + + this.inner = Object.freeze(inner); + } + static new( +inner: {message: string }): TokenRefused_ { + return new TokenRefused_(inner); + } + + static instanceOf(obj: any): obj is TokenRefused_ { + return obj.tag === FfiJoinError_Tags.TokenRefused; + } + + } + + type EncryptionSetup__interface = { + tag: FfiJoinError_Tags.EncryptionSetup; + inner: +Readonly<{message: string}> + }; + class EncryptionSetup_ extends UniffiEnum implements EncryptionSetup__interface { + /** + * @private + * This field is private and should not be used, use `tag` instead. + */ + readonly [uniffiTypeNameSymbol] = "FfiJoinError"; + readonly tag = FfiJoinError_Tags.EncryptionSetup; + readonly inner: +Readonly<{message: string}>; + constructor( +inner: {message: string }) { + super("FfiJoinError", "EncryptionSetup"); + + this.inner = Object.freeze(inner); + } + static new( +inner: {message: string }): EncryptionSetup_ { + return new EncryptionSetup_(inner); + } + + static instanceOf(obj: any): obj is EncryptionSetup_ { + return obj.tag === FfiJoinError_Tags.EncryptionSetup; + } + + } + + type Driver__interface = { + tag: FfiJoinError_Tags.Driver; + inner: +Readonly<{message: string}> + }; + class Driver_ extends UniffiEnum implements Driver__interface { + /** + * @private + * This field is private and should not be used, use `tag` instead. + */ + readonly [uniffiTypeNameSymbol] = "FfiJoinError"; + readonly tag = FfiJoinError_Tags.Driver; + readonly inner: +Readonly<{message: string}>; + constructor( +inner: {message: string }) { + super("FfiJoinError", "Driver"); + + this.inner = Object.freeze(inner); + } + static new( +inner: {message: string }): Driver_ { + return new Driver_(inner); + } + + static instanceOf(obj: any): obj is Driver_ { + return obj.tag === FfiJoinError_Tags.Driver; + } + + } + + function instanceOf(obj: any): obj is FfiJoinError { + return obj[uniffiTypeNameSymbol] === "FfiJoinError"; + } + + return Object.freeze({ + instanceOf, + AlreadyJoined: AlreadyJoined_, + InvalidParams: InvalidParams_, + SlotClosed: SlotClosed_, + NoTransport: NoTransport_, + TokenRefused: TokenRefused_, + EncryptionSetup: EncryptionSetup_, + Driver: Driver_ + }); + +})(); +/** + * Why a join failed. Typed so a host can decide what to offer next: + * `NoTransport` is a configuration problem, `TokenRefused` may be worth a + * retry. + */ +export type FfiJoinError = InstanceType< + typeof FfiJoinError['AlreadyJoined' | 'InvalidParams' | 'SlotClosed' | 'NoTransport' | 'TokenRefused' | 'EncryptionSetup' | 'Driver'] +>; + +// FfiConverter for enum FfiJoinError +const FfiConverterTypeFfiJoinError = (() => { + type TypeName = FfiJoinError; + class FFIConverter extends AbstractFfiConverterByteArray { + readFromCursor(c: Cursor): TypeName { + switch (c.readI32()) { + case 1: return new FfiJoinError.AlreadyJoined(); + case 2: return new FfiJoinError.InvalidParams({message: FfiConverterString.readFromCursor(c) }); + case 3: return new FfiJoinError.SlotClosed(); + case 4: return new FfiJoinError.NoTransport({message: FfiConverterString.readFromCursor(c) }); + case 5: return new FfiJoinError.TokenRefused({message: FfiConverterString.readFromCursor(c) }); + case 6: return new FfiJoinError.EncryptionSetup({message: FfiConverterString.readFromCursor(c) }); + case 7: return new FfiJoinError.Driver({message: FfiConverterString.readFromCursor(c) }); + default: throw new UniffiInternalError.UnexpectedEnumCase(); + } + } + writeIntoCursor(value: TypeName, c: Cursor): void { + switch (value.tag) { + case FfiJoinError_Tags.AlreadyJoined: { + c.writeI32(1); + return; + } + case FfiJoinError_Tags.InvalidParams: { + c.writeI32(2); + const inner = value.inner; + FfiConverterString.writeIntoCursor(inner.message, c); + return; + } + case FfiJoinError_Tags.SlotClosed: { + c.writeI32(3); + return; + } + case FfiJoinError_Tags.NoTransport: { + c.writeI32(4); + const inner = value.inner; + FfiConverterString.writeIntoCursor(inner.message, c); + return; + } + case FfiJoinError_Tags.TokenRefused: { + c.writeI32(5); + const inner = value.inner; + FfiConverterString.writeIntoCursor(inner.message, c); + return; + } + case FfiJoinError_Tags.EncryptionSetup: { + c.writeI32(6); + const inner = value.inner; + FfiConverterString.writeIntoCursor(inner.message, c); + return; + } + case FfiJoinError_Tags.Driver: { + c.writeI32(7); + const inner = value.inner; + FfiConverterString.writeIntoCursor(inner.message, c); + return; + } + default: + // Throwing from here means that FfiJoinError_Tags hasn't matched an ordinal. + throw new UniffiInternalError.UnexpectedEnumCase(); + } + } + allocationSize(value: TypeName): number { + switch (value.tag) { + case FfiJoinError_Tags.AlreadyJoined: { + return 4; + } + case FfiJoinError_Tags.InvalidParams: { + const inner = value.inner; + let size = 4; + size += FfiConverterString.allocationSize(inner.message); + return size; + } + case FfiJoinError_Tags.SlotClosed: { + return 4; + } + case FfiJoinError_Tags.NoTransport: { + const inner = value.inner; + let size = 4; + size += FfiConverterString.allocationSize(inner.message); + return size; + } + case FfiJoinError_Tags.TokenRefused: { + const inner = value.inner; + let size = 4; + size += FfiConverterString.allocationSize(inner.message); + return size; + } + case FfiJoinError_Tags.EncryptionSetup: { + const inner = value.inner; + let size = 4; + size += FfiConverterString.allocationSize(inner.message); + return size; + } + case FfiJoinError_Tags.Driver: { + const inner = value.inner; + let size = 4; + size += FfiConverterString.allocationSize(inner.message); + return size; + } + default: throw new UniffiInternalError.UnexpectedEnumCase(); + } + } + } + return new FFIConverter(); +})(); + + +// Enum: FfiDisconnectCause +export enum FfiDisconnectCause_Tags { + NeverJoined = "NeverJoined", + LeftByHost = "LeftByHost", + SlotClosed = "SlotClosed", + JoinFailed = "JoinFailed", + ManagerStopped = "ManagerStopped" +} +/** + * Why we are not in a call. Terminal by construction: unlike an impairment, + * none of these clears on its own. + */ +export const FfiDisconnectCause = (() => { + + type NeverJoined__interface = { + tag: FfiDisconnectCause_Tags.NeverJoined + }; + /** + * No join has been attempted on this manager. + */ + class NeverJoined_ extends UniffiEnum implements NeverJoined__interface { + /** + * @private + * This field is private and should not be used, use `tag` instead. + */ + readonly [uniffiTypeNameSymbol] = "FfiDisconnectCause"; + readonly tag = FfiDisconnectCause_Tags.NeverJoined; + constructor() { + super("FfiDisconnectCause", "NeverJoined"); + } + + static new(): NeverJoined_ { + return new NeverJoined_(); + } + + static instanceOf(obj: any): obj is NeverJoined_ { + return obj.tag === FfiDisconnectCause_Tags.NeverJoined; + } + + } + + type LeftByHost__interface = { + tag: FfiDisconnectCause_Tags.LeftByHost; + inner: +Readonly<{code?: string; reason?: string}> + }; + /** + * The host called `leave()`. + */ + class LeftByHost_ extends UniffiEnum implements LeftByHost__interface { + /** + * @private + * This field is private and should not be used, use `tag` instead. + */ + readonly [uniffiTypeNameSymbol] = "FfiDisconnectCause"; + readonly tag = FfiDisconnectCause_Tags.LeftByHost; + readonly inner: +Readonly<{code?: string; reason?: string}>; + constructor( +inner: {code?: string; reason?: string }) { + super("FfiDisconnectCause", "LeftByHost"); + + this.inner = Object.freeze(inner); + } + static new( +inner: {code?: string; reason?: string }): LeftByHost_ { + return new LeftByHost_(inner); + } + + static instanceOf(obj: any): obj is LeftByHost_ { + return obj.tag === FfiDisconnectCause_Tags.LeftByHost; + } + + } + + type SlotClosed__interface = { + tag: FfiDisconnectCause_Tags.SlotClosed + }; + /** + * The slot was closed under us and the machine left on its own. + */ + class SlotClosed_ extends UniffiEnum implements SlotClosed__interface { + /** + * @private + * This field is private and should not be used, use `tag` instead. + */ + readonly [uniffiTypeNameSymbol] = "FfiDisconnectCause"; + readonly tag = FfiDisconnectCause_Tags.SlotClosed; + constructor() { + super("FfiDisconnectCause", "SlotClosed"); + } + + static new(): SlotClosed_ { + return new SlotClosed_(); + } + + static instanceOf(obj: any): obj is SlotClosed_ { + return obj.tag === FfiDisconnectCause_Tags.SlotClosed; + } + + } + + type JoinFailed__interface = { + tag: FfiDisconnectCause_Tags.JoinFailed; + inner: +Readonly<{atTs: bigint; progress: FfiJoinProgress; error: FfiJoinError}> + }; + /** + * `join()` failed; the participation never started. `progress` says how + * far it got. + */ + class JoinFailed_ extends UniffiEnum implements JoinFailed__interface { + /** + * @private + * This field is private and should not be used, use `tag` instead. + */ + readonly [uniffiTypeNameSymbol] = "FfiDisconnectCause"; + readonly tag = FfiDisconnectCause_Tags.JoinFailed; + readonly inner: +Readonly<{atTs: bigint; progress: FfiJoinProgress; error: FfiJoinError}>; + constructor( +inner: {atTs: bigint; progress: FfiJoinProgress; error: FfiJoinError }) { + super("FfiDisconnectCause", "JoinFailed"); + + this.inner = Object.freeze(inner); + } + static new( +inner: {atTs: bigint; progress: FfiJoinProgress; error: FfiJoinError }): JoinFailed_ { + return new JoinFailed_(inner); + } + + static instanceOf(obj: any): obj is JoinFailed_ { + return obj.tag === FfiDisconnectCause_Tags.JoinFailed; + } + + } + + type ManagerStopped__interface = { + tag: FfiDisconnectCause_Tags.ManagerStopped; + inner: +Readonly<{component: FfiComponent}> + }; + /** + * A pump stopped. The manager is dead and will not recover; build a new + * one. + */ + class ManagerStopped_ extends UniffiEnum implements ManagerStopped__interface { + /** + * @private + * This field is private and should not be used, use `tag` instead. + */ + readonly [uniffiTypeNameSymbol] = "FfiDisconnectCause"; + readonly tag = FfiDisconnectCause_Tags.ManagerStopped; + readonly inner: +Readonly<{component: FfiComponent}>; + constructor( +inner: {component: FfiComponent }) { + super("FfiDisconnectCause", "ManagerStopped"); + + this.inner = Object.freeze(inner); + } + static new( +inner: {component: FfiComponent }): ManagerStopped_ { + return new ManagerStopped_(inner); + } + + static instanceOf(obj: any): obj is ManagerStopped_ { + return obj.tag === FfiDisconnectCause_Tags.ManagerStopped; + } + + } + + function instanceOf(obj: any): obj is FfiDisconnectCause { + return obj[uniffiTypeNameSymbol] === "FfiDisconnectCause"; + } + + return Object.freeze({ + instanceOf, + NeverJoined: NeverJoined_, + LeftByHost: LeftByHost_, + SlotClosed: SlotClosed_, + JoinFailed: JoinFailed_, + ManagerStopped: ManagerStopped_ + }); + +})(); +/** + * Why we are not in a call. Terminal by construction: unlike an impairment, + * none of these clears on its own. + */ +export type FfiDisconnectCause = InstanceType< + typeof FfiDisconnectCause['NeverJoined' | 'LeftByHost' | 'SlotClosed' | 'JoinFailed' | 'ManagerStopped'] +>; + +// FfiConverter for enum FfiDisconnectCause +const FfiConverterTypeFfiDisconnectCause = (() => { + type TypeName = FfiDisconnectCause; + class FFIConverter extends AbstractFfiConverterByteArray { + readFromCursor(c: Cursor): TypeName { + switch (c.readI32()) { + case 1: return new FfiDisconnectCause.NeverJoined(); + case 2: return new FfiDisconnectCause.LeftByHost({code: FfiConverterOptionalString.readFromCursor(c), reason: FfiConverterOptionalString.readFromCursor(c) }); + case 3: return new FfiDisconnectCause.SlotClosed(); + case 4: return new FfiDisconnectCause.JoinFailed({atTs: FfiConverterUInt64.readFromCursor(c), progress: FfiConverterTypeFfiJoinProgress.readFromCursor(c), error: FfiConverterTypeFfiJoinError.readFromCursor(c) }); + case 5: return new FfiDisconnectCause.ManagerStopped({component: FfiConverterTypeFfiComponent.readFromCursor(c) }); + default: throw new UniffiInternalError.UnexpectedEnumCase(); + } + } + writeIntoCursor(value: TypeName, c: Cursor): void { + switch (value.tag) { + case FfiDisconnectCause_Tags.NeverJoined: { + c.writeI32(1); + return; + } + case FfiDisconnectCause_Tags.LeftByHost: { + c.writeI32(2); + const inner = value.inner; + FfiConverterOptionalString.writeIntoCursor(inner.code, c); + FfiConverterOptionalString.writeIntoCursor(inner.reason, c); + return; + } + case FfiDisconnectCause_Tags.SlotClosed: { + c.writeI32(3); + return; + } + case FfiDisconnectCause_Tags.JoinFailed: { + c.writeI32(4); + const inner = value.inner; + FfiConverterUInt64.writeIntoCursor(inner.atTs, c); + FfiConverterTypeFfiJoinProgress.writeIntoCursor(inner.progress, c); + FfiConverterTypeFfiJoinError.writeIntoCursor(inner.error, c); + return; + } + case FfiDisconnectCause_Tags.ManagerStopped: { + c.writeI32(5); + const inner = value.inner; + FfiConverterTypeFfiComponent.writeIntoCursor(inner.component, c); + return; + } + default: + // Throwing from here means that FfiDisconnectCause_Tags hasn't matched an ordinal. + throw new UniffiInternalError.UnexpectedEnumCase(); + } + } + allocationSize(value: TypeName): number { + switch (value.tag) { + case FfiDisconnectCause_Tags.NeverJoined: { + return 4; + } + case FfiDisconnectCause_Tags.LeftByHost: { + const inner = value.inner; + let size = 4; + size += FfiConverterOptionalString.allocationSize(inner.code); + size += FfiConverterOptionalString.allocationSize(inner.reason); + return size; + } + case FfiDisconnectCause_Tags.SlotClosed: { + return 4; + } + case FfiDisconnectCause_Tags.JoinFailed: { + const inner = value.inner; + let size = 4; + size += FfiConverterUInt64.allocationSize(inner.atTs); + size += FfiConverterTypeFfiJoinProgress.allocationSize(inner.progress); + size += FfiConverterTypeFfiJoinError.allocationSize(inner.error); + return size; + } + case FfiDisconnectCause_Tags.ManagerStopped: { + const inner = value.inner; + let size = 4; + size += FfiConverterTypeFfiComponent.allocationSize(inner.component); + return size; + } + default: throw new UniffiInternalError.UnexpectedEnumCase(); + } + } + } + return new FFIConverter(); +})(); + + +// Enum: FfiEncryptionStatus +export enum FfiEncryptionStatus_Tags { + Joining = "Joining", + Connected = "Connected" +} +/** + * The media-key exchange as a whole. + */ +export const FfiEncryptionStatus = (() => { + + type Joining__interface = { + tag: FfiEncryptionStatus_Tags.Joining; + inner: +Readonly<{hasDistributedInitialKeys: boolean; hasReceivedAllMemberKeys: boolean}> + }; + class Joining_ extends UniffiEnum implements Joining__interface { + /** + * @private + * This field is private and should not be used, use `tag` instead. + */ + readonly [uniffiTypeNameSymbol] = "FfiEncryptionStatus"; + readonly tag = FfiEncryptionStatus_Tags.Joining; + readonly inner: +Readonly<{hasDistributedInitialKeys: boolean; hasReceivedAllMemberKeys: boolean}>; + constructor( +inner: {hasDistributedInitialKeys: boolean; hasReceivedAllMemberKeys: boolean }) { + super("FfiEncryptionStatus", "Joining"); + + this.inner = Object.freeze(inner); + } + static new( +inner: {hasDistributedInitialKeys: boolean; hasReceivedAllMemberKeys: boolean }): Joining_ { + return new Joining_(inner); + } + + static instanceOf(obj: any): obj is Joining_ { + return obj.tag === FfiEncryptionStatus_Tags.Joining; + } + + } + + type Connected__interface = { + tag: FfiEncryptionStatus_Tags.Connected; + inner: +Readonly<{leftMembersWithKeys: Array; fullySettled: boolean; lastRotationTs: bigint}> + }; + class Connected_ extends UniffiEnum implements Connected__interface { + /** + * @private + * This field is private and should not be used, use `tag` instead. + */ + readonly [uniffiTypeNameSymbol] = "FfiEncryptionStatus"; + readonly tag = FfiEncryptionStatus_Tags.Connected; + readonly inner: +Readonly<{leftMembersWithKeys: Array; fullySettled: boolean; lastRotationTs: bigint}>; + constructor( +inner: {leftMembersWithKeys: Array; fullySettled: boolean; lastRotationTs: bigint }) { + super("FfiEncryptionStatus", "Connected"); + + this.inner = Object.freeze(inner); + } + static new( +inner: {leftMembersWithKeys: Array; fullySettled: boolean; lastRotationTs: bigint }): Connected_ { + return new Connected_(inner); + } + + static instanceOf(obj: any): obj is Connected_ { + return obj.tag === FfiEncryptionStatus_Tags.Connected; + } + + } + + function instanceOf(obj: any): obj is FfiEncryptionStatus { + return obj[uniffiTypeNameSymbol] === "FfiEncryptionStatus"; + } + + return Object.freeze({ + instanceOf, + Joining: Joining_, + Connected: Connected_ + }); + +})(); +/** + * The media-key exchange as a whole. + */ +export type FfiEncryptionStatus = InstanceType< + typeof FfiEncryptionStatus['Joining' | 'Connected'] +>; + +// FfiConverter for enum FfiEncryptionStatus +const FfiConverterTypeFfiEncryptionStatus = (() => { + type TypeName = FfiEncryptionStatus; + class FFIConverter extends AbstractFfiConverterByteArray { + readFromCursor(c: Cursor): TypeName { + switch (c.readI32()) { + case 1: return new FfiEncryptionStatus.Joining({hasDistributedInitialKeys: FfiConverterBool.readFromCursor(c), hasReceivedAllMemberKeys: FfiConverterBool.readFromCursor(c) }); + case 2: return new FfiEncryptionStatus.Connected({leftMembersWithKeys: FfiConverterSequenceTypeFfiMember.readFromCursor(c), fullySettled: FfiConverterBool.readFromCursor(c), lastRotationTs: FfiConverterUInt64.readFromCursor(c) }); + default: throw new UniffiInternalError.UnexpectedEnumCase(); + } + } + writeIntoCursor(value: TypeName, c: Cursor): void { + switch (value.tag) { + case FfiEncryptionStatus_Tags.Joining: { + c.writeI32(1); + const inner = value.inner; + FfiConverterBool.writeIntoCursor(inner.hasDistributedInitialKeys, c); + FfiConverterBool.writeIntoCursor(inner.hasReceivedAllMemberKeys, c); + return; + } + case FfiEncryptionStatus_Tags.Connected: { + c.writeI32(2); + const inner = value.inner; + FfiConverterSequenceTypeFfiMember.writeIntoCursor(inner.leftMembersWithKeys, c); + FfiConverterBool.writeIntoCursor(inner.fullySettled, c); + FfiConverterUInt64.writeIntoCursor(inner.lastRotationTs, c); + return; + } + default: + // Throwing from here means that FfiEncryptionStatus_Tags hasn't matched an ordinal. + throw new UniffiInternalError.UnexpectedEnumCase(); + } + } + allocationSize(value: TypeName): number { + switch (value.tag) { + case FfiEncryptionStatus_Tags.Joining: { + const inner = value.inner; + let size = 4; + size += FfiConverterBool.allocationSize(inner.hasDistributedInitialKeys); + size += FfiConverterBool.allocationSize(inner.hasReceivedAllMemberKeys); + return size; + } + case FfiEncryptionStatus_Tags.Connected: { + const inner = value.inner; + let size = 4; + size += FfiConverterSequenceTypeFfiMember.allocationSize(inner.leftMembersWithKeys); + size += FfiConverterBool.allocationSize(inner.fullySettled); + size += FfiConverterUInt64.allocationSize(inner.lastRotationTs); + return size; + } + default: throw new UniffiInternalError.UnexpectedEnumCase(); + } + } + } + return new FFIConverter(); +})(); + + +// Enum: FfiEventOrigin +export enum FfiEventOrigin_Tags { + Encrypted = "Encrypted", + Cleartext = "Cleartext", + Unknown = "Unknown" +} +export const FfiEventOrigin = (() => { + + type Encrypted__interface = { + tag: FfiEventOrigin_Tags.Encrypted; + inner: +Readonly<{senderDeviceId?: string}> + }; + class Encrypted_ extends UniffiEnum implements Encrypted__interface { + /** + * @private + * This field is private and should not be used, use `tag` instead. + */ + readonly [uniffiTypeNameSymbol] = "FfiEventOrigin"; + readonly tag = FfiEventOrigin_Tags.Encrypted; + readonly inner: +Readonly<{senderDeviceId?: string}>; + constructor( +inner: {senderDeviceId?: string }) { + super("FfiEventOrigin", "Encrypted"); + + this.inner = Object.freeze(inner); + } + static new( +inner: {senderDeviceId?: string }): Encrypted_ { + return new Encrypted_(inner); + } + + static instanceOf(obj: any): obj is Encrypted_ { + return obj.tag === FfiEventOrigin_Tags.Encrypted; + } + + } + + type Cleartext__interface = { + tag: FfiEventOrigin_Tags.Cleartext + }; + class Cleartext_ extends UniffiEnum implements Cleartext__interface { + /** + * @private + * This field is private and should not be used, use `tag` instead. + */ + readonly [uniffiTypeNameSymbol] = "FfiEventOrigin"; + readonly tag = FfiEventOrigin_Tags.Cleartext; + constructor() { + super("FfiEventOrigin", "Cleartext"); + } + + static new(): Cleartext_ { + return new Cleartext_(); + } + + static instanceOf(obj: any): obj is Cleartext_ { + return obj.tag === FfiEventOrigin_Tags.Cleartext; + } + + } + + type Unknown__interface = { + tag: FfiEventOrigin_Tags.Unknown + }; + class Unknown_ extends UniffiEnum implements Unknown__interface { + /** + * @private + * This field is private and should not be used, use `tag` instead. + */ + readonly [uniffiTypeNameSymbol] = "FfiEventOrigin"; + readonly tag = FfiEventOrigin_Tags.Unknown; + constructor() { + super("FfiEventOrigin", "Unknown"); + } + + static new(): Unknown_ { + return new Unknown_(); + } + + static instanceOf(obj: any): obj is Unknown_ { + return obj.tag === FfiEventOrigin_Tags.Unknown; + } + + } + + function instanceOf(obj: any): obj is FfiEventOrigin { + return obj[uniffiTypeNameSymbol] === "FfiEventOrigin"; + } + + return Object.freeze({ + instanceOf, + Encrypted: Encrypted_, + Cleartext: Cleartext_, + Unknown: Unknown_ + }); + +})(); +export type FfiEventOrigin = InstanceType< + typeof FfiEventOrigin['Encrypted' | 'Cleartext' | 'Unknown'] +>; + +// FfiConverter for enum FfiEventOrigin +const FfiConverterTypeFfiEventOrigin = (() => { + type TypeName = FfiEventOrigin; + class FFIConverter extends AbstractFfiConverterByteArray { + readFromCursor(c: Cursor): TypeName { + switch (c.readI32()) { + case 1: return new FfiEventOrigin.Encrypted({senderDeviceId: FfiConverterOptionalString.readFromCursor(c) }); + case 2: return new FfiEventOrigin.Cleartext(); + case 3: return new FfiEventOrigin.Unknown(); + default: throw new UniffiInternalError.UnexpectedEnumCase(); + } + } + writeIntoCursor(value: TypeName, c: Cursor): void { + switch (value.tag) { + case FfiEventOrigin_Tags.Encrypted: { + c.writeI32(1); + const inner = value.inner; + FfiConverterOptionalString.writeIntoCursor(inner.senderDeviceId, c); + return; + } + case FfiEventOrigin_Tags.Cleartext: { + c.writeI32(2); + return; + } + case FfiEventOrigin_Tags.Unknown: { + c.writeI32(3); + return; + } + default: + // Throwing from here means that FfiEventOrigin_Tags hasn't matched an ordinal. + throw new UniffiInternalError.UnexpectedEnumCase(); + } + } + allocationSize(value: TypeName): number { + switch (value.tag) { + case FfiEventOrigin_Tags.Encrypted: { + const inner = value.inner; + let size = 4; + size += FfiConverterOptionalString.allocationSize(inner.senderDeviceId); + return size; + } + case FfiEventOrigin_Tags.Cleartext: { + return 4; + } + case FfiEventOrigin_Tags.Unknown: { + return 4; + } + default: throw new UniffiInternalError.UnexpectedEnumCase(); + } + } + } + return new FFIConverter(); +})(); + + +// Enum: FfiImpairment +export enum FfiImpairment_Tags { + HomeserverUnreachable = "HomeserverUnreachable", + KeepAliveRestartFailing = "KeepAliveRestartFailing", + KeepAliveExpired = "KeepAliveExpired", + KeepAliveUnavailable = "KeepAliveUnavailable", + MembershipRefreshFailing = "MembershipRefreshFailing", + OwnMembershipMissing = "OwnMembershipMissing", + OwnMembershipExcluded = "OwnMembershipExcluded", + MediaKeyNotDelivered = "MediaKeyNotDelivered", + MediaKeyNotReceived = "MediaKeyNotReceived", + MediaKeyRejected = "MediaKeyRejected", + ConnectionUnavailable = "ConnectionUnavailable", + ConnectionTokenExpired = "ConnectionTokenExpired", + SessionStateUnread = "SessionStateUnread", + JoinedBeforeSeed = "JoinedBeforeSeed" +} +/** + * A condition that is true right now and that the crate is still working + * on. Every variant clears by itself when the underlying operation + * succeeds — an impairment is never terminal; anything terminal ends the + * participation and appears as [`FfiDisconnectCause`] instead. + * + * A host that renders one warning banner can read this list and nothing + * else; the structured status above is for anything that needs the details. + */ +export const FfiImpairment = (() => { + + type HomeserverUnreachable__interface = { + tag: FfiImpairment_Tags.HomeserverUnreachable; + inner: +Readonly<{sinceTs: bigint}> + }; + /** + * The driver reports the homeserver unreachable; clears when it is back. + */ + class HomeserverUnreachable_ extends UniffiEnum implements HomeserverUnreachable__interface { + /** + * @private + * This field is private and should not be used, use `tag` instead. + */ + readonly [uniffiTypeNameSymbol] = "FfiImpairment"; + readonly tag = FfiImpairment_Tags.HomeserverUnreachable; + readonly inner: +Readonly<{sinceTs: bigint}>; + constructor( +inner: {sinceTs: bigint }) { + super("FfiImpairment", "HomeserverUnreachable"); + + this.inner = Object.freeze(inner); + } + static new( +inner: {sinceTs: bigint }): HomeserverUnreachable_ { + return new HomeserverUnreachable_(inner); + } + + static instanceOf(obj: any): obj is HomeserverUnreachable_ { + return obj.tag === FfiImpairment_Tags.HomeserverUnreachable; + } + + } + + type KeepAliveRestartFailing__interface = { + tag: FfiImpairment_Tags.KeepAliveRestartFailing; + inner: +Readonly<{sinceTs: bigint; firesAtTs: bigint; lastError: string}> + }; + class KeepAliveRestartFailing_ extends UniffiEnum implements KeepAliveRestartFailing__interface { + /** + * @private + * This field is private and should not be used, use `tag` instead. + */ + readonly [uniffiTypeNameSymbol] = "FfiImpairment"; + readonly tag = FfiImpairment_Tags.KeepAliveRestartFailing; + readonly inner: +Readonly<{sinceTs: bigint; firesAtTs: bigint; lastError: string}>; + constructor( +inner: {sinceTs: bigint; firesAtTs: bigint; lastError: string }) { + super("FfiImpairment", "KeepAliveRestartFailing"); + + this.inner = Object.freeze(inner); + } + static new( +inner: {sinceTs: bigint; firesAtTs: bigint; lastError: string }): KeepAliveRestartFailing_ { + return new KeepAliveRestartFailing_(inner); + } + + static instanceOf(obj: any): obj is KeepAliveRestartFailing_ { + return obj.tag === FfiImpairment_Tags.KeepAliveRestartFailing; + } + + } + + type KeepAliveExpired__interface = { + tag: FfiImpairment_Tags.KeepAliveExpired; + inner: +Readonly<{sinceTs: bigint}> + }; + class KeepAliveExpired_ extends UniffiEnum implements KeepAliveExpired__interface { + /** + * @private + * This field is private and should not be used, use `tag` instead. + */ + readonly [uniffiTypeNameSymbol] = "FfiImpairment"; + readonly tag = FfiImpairment_Tags.KeepAliveExpired; + readonly inner: +Readonly<{sinceTs: bigint}>; + constructor( +inner: {sinceTs: bigint }) { + super("FfiImpairment", "KeepAliveExpired"); + + this.inner = Object.freeze(inner); + } + static new( +inner: {sinceTs: bigint }): KeepAliveExpired_ { + return new KeepAliveExpired_(inner); + } + + static instanceOf(obj: any): obj is KeepAliveExpired_ { + return obj.tag === FfiImpairment_Tags.KeepAliveExpired; + } + + } + + type KeepAliveUnavailable__interface = { + tag: FfiImpairment_Tags.KeepAliveUnavailable; + inner: +Readonly<{permanent: boolean; membershipExpiresAtTs: bigint}> + }; + class KeepAliveUnavailable_ extends UniffiEnum implements KeepAliveUnavailable__interface { + /** + * @private + * This field is private and should not be used, use `tag` instead. + */ + readonly [uniffiTypeNameSymbol] = "FfiImpairment"; + readonly tag = FfiImpairment_Tags.KeepAliveUnavailable; + readonly inner: +Readonly<{permanent: boolean; membershipExpiresAtTs: bigint}>; + constructor( +inner: {permanent: boolean; membershipExpiresAtTs: bigint }) { + super("FfiImpairment", "KeepAliveUnavailable"); + + this.inner = Object.freeze(inner); + } + static new( +inner: {permanent: boolean; membershipExpiresAtTs: bigint }): KeepAliveUnavailable_ { + return new KeepAliveUnavailable_(inner); + } + + static instanceOf(obj: any): obj is KeepAliveUnavailable_ { + return obj.tag === FfiImpairment_Tags.KeepAliveUnavailable; + } + + } + + type MembershipRefreshFailing__interface = { + tag: FfiImpairment_Tags.MembershipRefreshFailing; + inner: +Readonly<{sinceTs: bigint; expiresAtTs: bigint; lastError: string}> + }; + class MembershipRefreshFailing_ extends UniffiEnum implements MembershipRefreshFailing__interface { + /** + * @private + * This field is private and should not be used, use `tag` instead. + */ + readonly [uniffiTypeNameSymbol] = "FfiImpairment"; + readonly tag = FfiImpairment_Tags.MembershipRefreshFailing; + readonly inner: +Readonly<{sinceTs: bigint; expiresAtTs: bigint; lastError: string}>; + constructor( +inner: {sinceTs: bigint; expiresAtTs: bigint; lastError: string }) { + super("FfiImpairment", "MembershipRefreshFailing"); + + this.inner = Object.freeze(inner); + } + static new( +inner: {sinceTs: bigint; expiresAtTs: bigint; lastError: string }): MembershipRefreshFailing_ { + return new MembershipRefreshFailing_(inner); + } + + static instanceOf(obj: any): obj is MembershipRefreshFailing_ { + return obj.tag === FfiImpairment_Tags.MembershipRefreshFailing; + } + + } + + type OwnMembershipMissing__interface = { + tag: FfiImpairment_Tags.OwnMembershipMissing; + inner: +Readonly<{sinceTs: bigint; republishedAtTs?: bigint}> + }; + class OwnMembershipMissing_ extends UniffiEnum implements OwnMembershipMissing__interface { + /** + * @private + * This field is private and should not be used, use `tag` instead. + */ + readonly [uniffiTypeNameSymbol] = "FfiImpairment"; + readonly tag = FfiImpairment_Tags.OwnMembershipMissing; + readonly inner: +Readonly<{sinceTs: bigint; republishedAtTs?: bigint}>; + constructor( +inner: {sinceTs: bigint; republishedAtTs?: bigint }) { + super("FfiImpairment", "OwnMembershipMissing"); + + this.inner = Object.freeze(inner); + } + static new( +inner: {sinceTs: bigint; republishedAtTs?: bigint }): OwnMembershipMissing_ { + return new OwnMembershipMissing_(inner); + } + + static instanceOf(obj: any): obj is OwnMembershipMissing_ { + return obj.tag === FfiImpairment_Tags.OwnMembershipMissing; + } + + } + + type OwnMembershipExcluded__interface = { + tag: FfiImpairment_Tags.OwnMembershipExcluded; + inner: +Readonly<{reason: FfiJoinExclusionReason}> + }; + class OwnMembershipExcluded_ extends UniffiEnum implements OwnMembershipExcluded__interface { + /** + * @private + * This field is private and should not be used, use `tag` instead. + */ + readonly [uniffiTypeNameSymbol] = "FfiImpairment"; + readonly tag = FfiImpairment_Tags.OwnMembershipExcluded; + readonly inner: +Readonly<{reason: FfiJoinExclusionReason}>; + constructor( +inner: {reason: FfiJoinExclusionReason }) { + super("FfiImpairment", "OwnMembershipExcluded"); + + this.inner = Object.freeze(inner); + } + static new( +inner: {reason: FfiJoinExclusionReason }): OwnMembershipExcluded_ { + return new OwnMembershipExcluded_(inner); + } + + static instanceOf(obj: any): obj is OwnMembershipExcluded_ { + return obj.tag === FfiImpairment_Tags.OwnMembershipExcluded; + } + + } + + type MediaKeyNotDelivered__interface = { + tag: FfiImpairment_Tags.MediaKeyNotDelivered; + inner: +Readonly<{memberIds: Array}> + }; + class MediaKeyNotDelivered_ extends UniffiEnum implements MediaKeyNotDelivered__interface { + /** + * @private + * This field is private and should not be used, use `tag` instead. + */ + readonly [uniffiTypeNameSymbol] = "FfiImpairment"; + readonly tag = FfiImpairment_Tags.MediaKeyNotDelivered; + readonly inner: +Readonly<{memberIds: Array}>; + constructor( +inner: {memberIds: Array }) { + super("FfiImpairment", "MediaKeyNotDelivered"); + + this.inner = Object.freeze(inner); + } + static new( +inner: {memberIds: Array }): MediaKeyNotDelivered_ { + return new MediaKeyNotDelivered_(inner); + } + + static instanceOf(obj: any): obj is MediaKeyNotDelivered_ { + return obj.tag === FfiImpairment_Tags.MediaKeyNotDelivered; + } + + } + + type MediaKeyNotReceived__interface = { + tag: FfiImpairment_Tags.MediaKeyNotReceived; + inner: +Readonly<{memberIds: Array}> + }; + class MediaKeyNotReceived_ extends UniffiEnum implements MediaKeyNotReceived__interface { + /** + * @private + * This field is private and should not be used, use `tag` instead. + */ + readonly [uniffiTypeNameSymbol] = "FfiImpairment"; + readonly tag = FfiImpairment_Tags.MediaKeyNotReceived; + readonly inner: +Readonly<{memberIds: Array}>; + constructor( +inner: {memberIds: Array }) { + super("FfiImpairment", "MediaKeyNotReceived"); + + this.inner = Object.freeze(inner); + } + static new( +inner: {memberIds: Array }): MediaKeyNotReceived_ { + return new MediaKeyNotReceived_(inner); + } + + static instanceOf(obj: any): obj is MediaKeyNotReceived_ { + return obj.tag === FfiImpairment_Tags.MediaKeyNotReceived; + } + + } + + type MediaKeyRejected__interface = { + tag: FfiImpairment_Tags.MediaKeyRejected; + inner: +Readonly<{memberId: string; senderUserId: string; reason: FfiKeyRejection; atTs: bigint}> + }; + class MediaKeyRejected_ extends UniffiEnum implements MediaKeyRejected__interface { + /** + * @private + * This field is private and should not be used, use `tag` instead. + */ + readonly [uniffiTypeNameSymbol] = "FfiImpairment"; + readonly tag = FfiImpairment_Tags.MediaKeyRejected; + readonly inner: +Readonly<{memberId: string; senderUserId: string; reason: FfiKeyRejection; atTs: bigint}>; + constructor( +inner: {memberId: string; senderUserId: string; reason: FfiKeyRejection; atTs: bigint }) { + super("FfiImpairment", "MediaKeyRejected"); + + this.inner = Object.freeze(inner); + } + static new( +inner: {memberId: string; senderUserId: string; reason: FfiKeyRejection; atTs: bigint }): MediaKeyRejected_ { + return new MediaKeyRejected_(inner); + } + + static instanceOf(obj: any): obj is MediaKeyRejected_ { + return obj.tag === FfiImpairment_Tags.MediaKeyRejected; + } + + } + + type ConnectionUnavailable__interface = { + tag: FfiImpairment_Tags.ConnectionUnavailable; + inner: +Readonly<{serviceUrl: string; memberIds: Array; lastError: string; retryAtTs: bigint}> + }; + class ConnectionUnavailable_ extends UniffiEnum implements ConnectionUnavailable__interface { + /** + * @private + * This field is private and should not be used, use `tag` instead. + */ + readonly [uniffiTypeNameSymbol] = "FfiImpairment"; + readonly tag = FfiImpairment_Tags.ConnectionUnavailable; + readonly inner: +Readonly<{serviceUrl: string; memberIds: Array; lastError: string; retryAtTs: bigint}>; + constructor( +inner: {serviceUrl: string; memberIds: Array; lastError: string; retryAtTs: bigint }) { + super("FfiImpairment", "ConnectionUnavailable"); + + this.inner = Object.freeze(inner); + } + static new( +inner: {serviceUrl: string; memberIds: Array; lastError: string; retryAtTs: bigint }): ConnectionUnavailable_ { + return new ConnectionUnavailable_(inner); + } + + static instanceOf(obj: any): obj is ConnectionUnavailable_ { + return obj.tag === FfiImpairment_Tags.ConnectionUnavailable; + } + + } + + type ConnectionTokenExpired__interface = { + tag: FfiImpairment_Tags.ConnectionTokenExpired; + inner: +Readonly<{serviceUrl: string; expiredAtTs: bigint; lastError: string}> + }; + class ConnectionTokenExpired_ extends UniffiEnum implements ConnectionTokenExpired__interface { + /** + * @private + * This field is private and should not be used, use `tag` instead. + */ + readonly [uniffiTypeNameSymbol] = "FfiImpairment"; + readonly tag = FfiImpairment_Tags.ConnectionTokenExpired; + readonly inner: +Readonly<{serviceUrl: string; expiredAtTs: bigint; lastError: string}>; + constructor( +inner: {serviceUrl: string; expiredAtTs: bigint; lastError: string }) { + super("FfiImpairment", "ConnectionTokenExpired"); + + this.inner = Object.freeze(inner); + } + static new( +inner: {serviceUrl: string; expiredAtTs: bigint; lastError: string }): ConnectionTokenExpired_ { + return new ConnectionTokenExpired_(inner); + } + + static instanceOf(obj: any): obj is ConnectionTokenExpired_ { + return obj.tag === FfiImpairment_Tags.ConnectionTokenExpired; + } + + } + + type SessionStateUnread__interface = { + tag: FfiImpairment_Tags.SessionStateUnread; + inner: +Readonly<{reads: Array}> + }; + class SessionStateUnread_ extends UniffiEnum implements SessionStateUnread__interface { + /** + * @private + * This field is private and should not be used, use `tag` instead. + */ + readonly [uniffiTypeNameSymbol] = "FfiImpairment"; + readonly tag = FfiImpairment_Tags.SessionStateUnread; + readonly inner: +Readonly<{reads: Array}>; + constructor( +inner: {reads: Array }) { + super("FfiImpairment", "SessionStateUnread"); + + this.inner = Object.freeze(inner); + } + static new( +inner: {reads: Array }): SessionStateUnread_ { + return new SessionStateUnread_(inner); + } + + static instanceOf(obj: any): obj is SessionStateUnread_ { + return obj.tag === FfiImpairment_Tags.SessionStateUnread; + } + + } + + type JoinedBeforeSeed__interface = { + tag: FfiImpairment_Tags.JoinedBeforeSeed; + inner: +Readonly<{atTs: bigint}> + }; + class JoinedBeforeSeed_ extends UniffiEnum implements JoinedBeforeSeed__interface { + /** + * @private + * This field is private and should not be used, use `tag` instead. + */ + readonly [uniffiTypeNameSymbol] = "FfiImpairment"; + readonly tag = FfiImpairment_Tags.JoinedBeforeSeed; + readonly inner: +Readonly<{atTs: bigint}>; + constructor( +inner: {atTs: bigint }) { + super("FfiImpairment", "JoinedBeforeSeed"); + + this.inner = Object.freeze(inner); + } + static new( +inner: {atTs: bigint }): JoinedBeforeSeed_ { + return new JoinedBeforeSeed_(inner); + } + + static instanceOf(obj: any): obj is JoinedBeforeSeed_ { + return obj.tag === FfiImpairment_Tags.JoinedBeforeSeed; + } + + } + + function instanceOf(obj: any): obj is FfiImpairment { + return obj[uniffiTypeNameSymbol] === "FfiImpairment"; + } + + return Object.freeze({ + instanceOf, + HomeserverUnreachable: HomeserverUnreachable_, + KeepAliveRestartFailing: KeepAliveRestartFailing_, + KeepAliveExpired: KeepAliveExpired_, + KeepAliveUnavailable: KeepAliveUnavailable_, + MembershipRefreshFailing: MembershipRefreshFailing_, + OwnMembershipMissing: OwnMembershipMissing_, + OwnMembershipExcluded: OwnMembershipExcluded_, + MediaKeyNotDelivered: MediaKeyNotDelivered_, + MediaKeyNotReceived: MediaKeyNotReceived_, + MediaKeyRejected: MediaKeyRejected_, + ConnectionUnavailable: ConnectionUnavailable_, + ConnectionTokenExpired: ConnectionTokenExpired_, + SessionStateUnread: SessionStateUnread_, + JoinedBeforeSeed: JoinedBeforeSeed_ + }); + +})(); +/** + * A condition that is true right now and that the crate is still working + * on. Every variant clears by itself when the underlying operation + * succeeds — an impairment is never terminal; anything terminal ends the + * participation and appears as [`FfiDisconnectCause`] instead. + * + * A host that renders one warning banner can read this list and nothing + * else; the structured status above is for anything that needs the details. + */ +export type FfiImpairment = InstanceType< + typeof FfiImpairment['HomeserverUnreachable' | 'KeepAliveRestartFailing' | 'KeepAliveExpired' | 'KeepAliveUnavailable' | 'MembershipRefreshFailing' | 'OwnMembershipMissing' | 'OwnMembershipExcluded' | 'MediaKeyNotDelivered' | 'MediaKeyNotReceived' | 'MediaKeyRejected' | 'ConnectionUnavailable' | 'ConnectionTokenExpired' | 'SessionStateUnread' | 'JoinedBeforeSeed'] +>; + +// FfiConverter for enum FfiImpairment +const FfiConverterTypeFfiImpairment = (() => { + type TypeName = FfiImpairment; + class FFIConverter extends AbstractFfiConverterByteArray { + readFromCursor(c: Cursor): TypeName { + switch (c.readI32()) { + case 1: return new FfiImpairment.HomeserverUnreachable({sinceTs: FfiConverterUInt64.readFromCursor(c) }); + case 2: return new FfiImpairment.KeepAliveRestartFailing({sinceTs: FfiConverterUInt64.readFromCursor(c), firesAtTs: FfiConverterUInt64.readFromCursor(c), lastError: FfiConverterString.readFromCursor(c) }); + case 3: return new FfiImpairment.KeepAliveExpired({sinceTs: FfiConverterUInt64.readFromCursor(c) }); + case 4: return new FfiImpairment.KeepAliveUnavailable({permanent: FfiConverterBool.readFromCursor(c), membershipExpiresAtTs: FfiConverterUInt64.readFromCursor(c) }); + case 5: return new FfiImpairment.MembershipRefreshFailing({sinceTs: FfiConverterUInt64.readFromCursor(c), expiresAtTs: FfiConverterUInt64.readFromCursor(c), lastError: FfiConverterString.readFromCursor(c) }); + case 6: return new FfiImpairment.OwnMembershipMissing({sinceTs: FfiConverterUInt64.readFromCursor(c), republishedAtTs: FfiConverterOptionalUInt64.readFromCursor(c) }); + case 7: return new FfiImpairment.OwnMembershipExcluded({reason: FfiConverterTypeFfiJoinExclusionReason.readFromCursor(c) }); + case 8: return new FfiImpairment.MediaKeyNotDelivered({memberIds: FfiConverterSequenceString.readFromCursor(c) }); + case 9: return new FfiImpairment.MediaKeyNotReceived({memberIds: FfiConverterSequenceString.readFromCursor(c) }); + case 10: return new FfiImpairment.MediaKeyRejected({memberId: FfiConverterString.readFromCursor(c), senderUserId: FfiConverterString.readFromCursor(c), reason: FfiConverterTypeFfiKeyRejection.readFromCursor(c), atTs: FfiConverterUInt64.readFromCursor(c) }); + case 11: return new FfiImpairment.ConnectionUnavailable({serviceUrl: FfiConverterString.readFromCursor(c), memberIds: FfiConverterSequenceString.readFromCursor(c), lastError: FfiConverterString.readFromCursor(c), retryAtTs: FfiConverterUInt64.readFromCursor(c) }); + case 12: return new FfiImpairment.ConnectionTokenExpired({serviceUrl: FfiConverterString.readFromCursor(c), expiredAtTs: FfiConverterUInt64.readFromCursor(c), lastError: FfiConverterString.readFromCursor(c) }); + case 13: return new FfiImpairment.SessionStateUnread({reads: FfiConverterSequenceTypeFfiSessionRead.readFromCursor(c) }); + case 14: return new FfiImpairment.JoinedBeforeSeed({atTs: FfiConverterUInt64.readFromCursor(c) }); + default: throw new UniffiInternalError.UnexpectedEnumCase(); + } + } + writeIntoCursor(value: TypeName, c: Cursor): void { + switch (value.tag) { + case FfiImpairment_Tags.HomeserverUnreachable: { + c.writeI32(1); + const inner = value.inner; + FfiConverterUInt64.writeIntoCursor(inner.sinceTs, c); + return; + } + case FfiImpairment_Tags.KeepAliveRestartFailing: { + c.writeI32(2); + const inner = value.inner; + FfiConverterUInt64.writeIntoCursor(inner.sinceTs, c); + FfiConverterUInt64.writeIntoCursor(inner.firesAtTs, c); + FfiConverterString.writeIntoCursor(inner.lastError, c); + return; + } + case FfiImpairment_Tags.KeepAliveExpired: { + c.writeI32(3); + const inner = value.inner; + FfiConverterUInt64.writeIntoCursor(inner.sinceTs, c); + return; + } + case FfiImpairment_Tags.KeepAliveUnavailable: { + c.writeI32(4); + const inner = value.inner; + FfiConverterBool.writeIntoCursor(inner.permanent, c); + FfiConverterUInt64.writeIntoCursor(inner.membershipExpiresAtTs, c); + return; + } + case FfiImpairment_Tags.MembershipRefreshFailing: { + c.writeI32(5); + const inner = value.inner; + FfiConverterUInt64.writeIntoCursor(inner.sinceTs, c); + FfiConverterUInt64.writeIntoCursor(inner.expiresAtTs, c); + FfiConverterString.writeIntoCursor(inner.lastError, c); + return; + } + case FfiImpairment_Tags.OwnMembershipMissing: { + c.writeI32(6); + const inner = value.inner; + FfiConverterUInt64.writeIntoCursor(inner.sinceTs, c); + FfiConverterOptionalUInt64.writeIntoCursor(inner.republishedAtTs, c); + return; + } + case FfiImpairment_Tags.OwnMembershipExcluded: { + c.writeI32(7); + const inner = value.inner; + FfiConverterTypeFfiJoinExclusionReason.writeIntoCursor(inner.reason, c); + return; + } + case FfiImpairment_Tags.MediaKeyNotDelivered: { + c.writeI32(8); + const inner = value.inner; + FfiConverterSequenceString.writeIntoCursor(inner.memberIds, c); + return; + } + case FfiImpairment_Tags.MediaKeyNotReceived: { + c.writeI32(9); + const inner = value.inner; + FfiConverterSequenceString.writeIntoCursor(inner.memberIds, c); + return; + } + case FfiImpairment_Tags.MediaKeyRejected: { + c.writeI32(10); + const inner = value.inner; + FfiConverterString.writeIntoCursor(inner.memberId, c); + FfiConverterString.writeIntoCursor(inner.senderUserId, c); + FfiConverterTypeFfiKeyRejection.writeIntoCursor(inner.reason, c); + FfiConverterUInt64.writeIntoCursor(inner.atTs, c); + return; + } + case FfiImpairment_Tags.ConnectionUnavailable: { + c.writeI32(11); + const inner = value.inner; + FfiConverterString.writeIntoCursor(inner.serviceUrl, c); + FfiConverterSequenceString.writeIntoCursor(inner.memberIds, c); + FfiConverterString.writeIntoCursor(inner.lastError, c); + FfiConverterUInt64.writeIntoCursor(inner.retryAtTs, c); + return; + } + case FfiImpairment_Tags.ConnectionTokenExpired: { + c.writeI32(12); + const inner = value.inner; + FfiConverterString.writeIntoCursor(inner.serviceUrl, c); + FfiConverterUInt64.writeIntoCursor(inner.expiredAtTs, c); + FfiConverterString.writeIntoCursor(inner.lastError, c); + return; + } + case FfiImpairment_Tags.SessionStateUnread: { + c.writeI32(13); + const inner = value.inner; + FfiConverterSequenceTypeFfiSessionRead.writeIntoCursor(inner.reads, c); + return; + } + case FfiImpairment_Tags.JoinedBeforeSeed: { + c.writeI32(14); + const inner = value.inner; + FfiConverterUInt64.writeIntoCursor(inner.atTs, c); + return; + } + default: + // Throwing from here means that FfiImpairment_Tags hasn't matched an ordinal. + throw new UniffiInternalError.UnexpectedEnumCase(); + } + } + allocationSize(value: TypeName): number { + switch (value.tag) { + case FfiImpairment_Tags.HomeserverUnreachable: { + const inner = value.inner; + let size = 4; + size += FfiConverterUInt64.allocationSize(inner.sinceTs); + return size; + } + case FfiImpairment_Tags.KeepAliveRestartFailing: { + const inner = value.inner; + let size = 4; + size += FfiConverterUInt64.allocationSize(inner.sinceTs); + size += FfiConverterUInt64.allocationSize(inner.firesAtTs); + size += FfiConverterString.allocationSize(inner.lastError); + return size; + } + case FfiImpairment_Tags.KeepAliveExpired: { + const inner = value.inner; + let size = 4; + size += FfiConverterUInt64.allocationSize(inner.sinceTs); + return size; + } + case FfiImpairment_Tags.KeepAliveUnavailable: { + const inner = value.inner; + let size = 4; + size += FfiConverterBool.allocationSize(inner.permanent); + size += FfiConverterUInt64.allocationSize(inner.membershipExpiresAtTs); + return size; + } + case FfiImpairment_Tags.MembershipRefreshFailing: { + const inner = value.inner; + let size = 4; + size += FfiConverterUInt64.allocationSize(inner.sinceTs); + size += FfiConverterUInt64.allocationSize(inner.expiresAtTs); + size += FfiConverterString.allocationSize(inner.lastError); + return size; + } + case FfiImpairment_Tags.OwnMembershipMissing: { + const inner = value.inner; + let size = 4; + size += FfiConverterUInt64.allocationSize(inner.sinceTs); + size += FfiConverterOptionalUInt64.allocationSize(inner.republishedAtTs); + return size; + } + case FfiImpairment_Tags.OwnMembershipExcluded: { + const inner = value.inner; + let size = 4; + size += FfiConverterTypeFfiJoinExclusionReason.allocationSize(inner.reason); + return size; + } + case FfiImpairment_Tags.MediaKeyNotDelivered: { + const inner = value.inner; + let size = 4; + size += FfiConverterSequenceString.allocationSize(inner.memberIds); + return size; + } + case FfiImpairment_Tags.MediaKeyNotReceived: { + const inner = value.inner; + let size = 4; + size += FfiConverterSequenceString.allocationSize(inner.memberIds); + return size; + } + case FfiImpairment_Tags.MediaKeyRejected: { + const inner = value.inner; + let size = 4; + size += FfiConverterString.allocationSize(inner.memberId); + size += FfiConverterString.allocationSize(inner.senderUserId); + size += FfiConverterTypeFfiKeyRejection.allocationSize(inner.reason); + size += FfiConverterUInt64.allocationSize(inner.atTs); + return size; + } + case FfiImpairment_Tags.ConnectionUnavailable: { + const inner = value.inner; + let size = 4; + size += FfiConverterString.allocationSize(inner.serviceUrl); + size += FfiConverterSequenceString.allocationSize(inner.memberIds); + size += FfiConverterString.allocationSize(inner.lastError); + size += FfiConverterUInt64.allocationSize(inner.retryAtTs); + return size; + } + case FfiImpairment_Tags.ConnectionTokenExpired: { + const inner = value.inner; + let size = 4; + size += FfiConverterString.allocationSize(inner.serviceUrl); + size += FfiConverterUInt64.allocationSize(inner.expiredAtTs); + size += FfiConverterString.allocationSize(inner.lastError); + return size; + } + case FfiImpairment_Tags.SessionStateUnread: { + const inner = value.inner; + let size = 4; + size += FfiConverterSequenceTypeFfiSessionRead.allocationSize(inner.reads); + return size; + } + case FfiImpairment_Tags.JoinedBeforeSeed: { + const inner = value.inner; + let size = 4; + size += FfiConverterUInt64.allocationSize(inner.atTs); + return size; + } + default: throw new UniffiInternalError.UnexpectedEnumCase(); + } + } + } + return new FFIConverter(); +})(); + + +// Enum: FfiKeepAlive +export enum FfiKeepAlive_Tags { + Armed = "Armed", + Delegated = "Delegated", + RestartFailing = "RestartFailing", + Expired = "Expired", + Unavailable = "Unavailable" +} +/** + * The dead man's switch that clears our membership if this client dies. + * Mutually exclusive states of one mechanism. + */ +export const FfiKeepAlive = (() => { + + type Armed__interface = { + tag: FfiKeepAlive_Tags.Armed; + inner: +Readonly<{delayMs: bigint; lastRestartTs: bigint; firesAtTs: bigint}> + }; + /** + * Armed, and we restart it ourselves. + */ + class Armed_ extends UniffiEnum implements Armed__interface { + /** + * @private + * This field is private and should not be used, use `tag` instead. + */ + readonly [uniffiTypeNameSymbol] = "FfiKeepAlive"; + readonly tag = FfiKeepAlive_Tags.Armed; + readonly inner: +Readonly<{delayMs: bigint; lastRestartTs: bigint; firesAtTs: bigint}>; + constructor( +inner: {delayMs: bigint; lastRestartTs: bigint; firesAtTs: bigint }) { + super("FfiKeepAlive", "Armed"); + + this.inner = Object.freeze(inner); + } + static new( +inner: {delayMs: bigint; lastRestartTs: bigint; firesAtTs: bigint }): Armed_ { + return new Armed_(inner); + } + + static instanceOf(obj: any): obj is Armed_ { + return obj.tag === FfiKeepAlive_Tags.Armed; + } + + } + + type Delegated__interface = { + tag: FfiKeepAlive_Tags.Delegated; + inner: +Readonly<{delegatedAtTs: bigint; earliestFireTs: bigint}> + }; + /** + * Handed to the SFU (MSC4195): we no longer restart it, so a frozen + * `last_restart_ts` is expected here rather than a fault. + */ + class Delegated_ extends UniffiEnum implements Delegated__interface { + /** + * @private + * This field is private and should not be used, use `tag` instead. + */ + readonly [uniffiTypeNameSymbol] = "FfiKeepAlive"; + readonly tag = FfiKeepAlive_Tags.Delegated; + readonly inner: +Readonly<{delegatedAtTs: bigint; earliestFireTs: bigint}>; + constructor( +inner: {delegatedAtTs: bigint; earliestFireTs: bigint }) { + super("FfiKeepAlive", "Delegated"); + + this.inner = Object.freeze(inner); + } + static new( +inner: {delegatedAtTs: bigint; earliestFireTs: bigint }): Delegated_ { + return new Delegated_(inner); + } + + static instanceOf(obj: any): obj is Delegated_ { + return obj.tag === FfiKeepAlive_Tags.Delegated; + } + + } + + type RestartFailing__interface = { + tag: FfiKeepAlive_Tags.RestartFailing; + inner: +Readonly<{sinceTs: bigint; firesAtTs: bigint; lastError: string}> + }; + /** + * Armed, but restarts are failing — we drop out at `fires_at_ts` + * unless one succeeds. + */ + class RestartFailing_ extends UniffiEnum implements RestartFailing__interface { + /** + * @private + * This field is private and should not be used, use `tag` instead. + */ + readonly [uniffiTypeNameSymbol] = "FfiKeepAlive"; + readonly tag = FfiKeepAlive_Tags.RestartFailing; + readonly inner: +Readonly<{sinceTs: bigint; firesAtTs: bigint; lastError: string}>; + constructor( +inner: {sinceTs: bigint; firesAtTs: bigint; lastError: string }) { + super("FfiKeepAlive", "RestartFailing"); + + this.inner = Object.freeze(inner); + } + static new( +inner: {sinceTs: bigint; firesAtTs: bigint; lastError: string }): RestartFailing_ { + return new RestartFailing_(inner); + } + + static instanceOf(obj: any): obj is RestartFailing_ { + return obj.tag === FfiKeepAlive_Tags.RestartFailing; + } + + } + + type Expired__interface = { + tag: FfiKeepAlive_Tags.Expired; + inner: +Readonly<{sinceTs: bigint}> + }; + /** + * Its delay elapsed with no successful restart: we are probably out + * already. A replacement is being armed. + */ + class Expired_ extends UniffiEnum implements Expired__interface { + /** + * @private + * This field is private and should not be used, use `tag` instead. + */ + readonly [uniffiTypeNameSymbol] = "FfiKeepAlive"; + readonly tag = FfiKeepAlive_Tags.Expired; + readonly inner: +Readonly<{sinceTs: bigint}>; + constructor( +inner: {sinceTs: bigint }) { + super("FfiKeepAlive", "Expired"); + + this.inner = Object.freeze(inner); + } + static new( +inner: {sinceTs: bigint }): Expired_ { + return new Expired_(inner); + } + + static instanceOf(obj: any): obj is Expired_ { + return obj.tag === FfiKeepAlive_Tags.Expired; + } + + } + + type Unavailable__interface = { + tag: FfiKeepAlive_Tags.Unavailable; + inner: +Readonly<{permanent: boolean; nextProbeTs?: bigint}> + }; + /** + * None armed. `permanent` = this homeserver refuses delayed events for + * good; otherwise we re-probe at `next_probe_ts` (`Some(0)` = next beat). + */ + class Unavailable_ extends UniffiEnum implements Unavailable__interface { + /** + * @private + * This field is private and should not be used, use `tag` instead. + */ + readonly [uniffiTypeNameSymbol] = "FfiKeepAlive"; + readonly tag = FfiKeepAlive_Tags.Unavailable; + readonly inner: +Readonly<{permanent: boolean; nextProbeTs?: bigint}>; + constructor( +inner: {permanent: boolean; nextProbeTs?: bigint }) { + super("FfiKeepAlive", "Unavailable"); + + this.inner = Object.freeze(inner); + } + static new( +inner: {permanent: boolean; nextProbeTs?: bigint }): Unavailable_ { + return new Unavailable_(inner); + } + + static instanceOf(obj: any): obj is Unavailable_ { + return obj.tag === FfiKeepAlive_Tags.Unavailable; + } + + } + + function instanceOf(obj: any): obj is FfiKeepAlive { + return obj[uniffiTypeNameSymbol] === "FfiKeepAlive"; + } + + return Object.freeze({ + instanceOf, + Armed: Armed_, + Delegated: Delegated_, + RestartFailing: RestartFailing_, + Expired: Expired_, + Unavailable: Unavailable_ + }); + +})(); +/** + * The dead man's switch that clears our membership if this client dies. + * Mutually exclusive states of one mechanism. + */ +export type FfiKeepAlive = InstanceType< + typeof FfiKeepAlive['Armed' | 'Delegated' | 'RestartFailing' | 'Expired' | 'Unavailable'] +>; + +// FfiConverter for enum FfiKeepAlive +const FfiConverterTypeFfiKeepAlive = (() => { + type TypeName = FfiKeepAlive; + class FFIConverter extends AbstractFfiConverterByteArray { + readFromCursor(c: Cursor): TypeName { + switch (c.readI32()) { + case 1: return new FfiKeepAlive.Armed({delayMs: FfiConverterUInt64.readFromCursor(c), lastRestartTs: FfiConverterUInt64.readFromCursor(c), firesAtTs: FfiConverterUInt64.readFromCursor(c) }); + case 2: return new FfiKeepAlive.Delegated({delegatedAtTs: FfiConverterUInt64.readFromCursor(c), earliestFireTs: FfiConverterUInt64.readFromCursor(c) }); + case 3: return new FfiKeepAlive.RestartFailing({sinceTs: FfiConverterUInt64.readFromCursor(c), firesAtTs: FfiConverterUInt64.readFromCursor(c), lastError: FfiConverterString.readFromCursor(c) }); + case 4: return new FfiKeepAlive.Expired({sinceTs: FfiConverterUInt64.readFromCursor(c) }); + case 5: return new FfiKeepAlive.Unavailable({permanent: FfiConverterBool.readFromCursor(c), nextProbeTs: FfiConverterOptionalUInt64.readFromCursor(c) }); + default: throw new UniffiInternalError.UnexpectedEnumCase(); + } + } + writeIntoCursor(value: TypeName, c: Cursor): void { + switch (value.tag) { + case FfiKeepAlive_Tags.Armed: { + c.writeI32(1); + const inner = value.inner; + FfiConverterUInt64.writeIntoCursor(inner.delayMs, c); + FfiConverterUInt64.writeIntoCursor(inner.lastRestartTs, c); + FfiConverterUInt64.writeIntoCursor(inner.firesAtTs, c); + return; + } + case FfiKeepAlive_Tags.Delegated: { + c.writeI32(2); + const inner = value.inner; + FfiConverterUInt64.writeIntoCursor(inner.delegatedAtTs, c); + FfiConverterUInt64.writeIntoCursor(inner.earliestFireTs, c); + return; + } + case FfiKeepAlive_Tags.RestartFailing: { + c.writeI32(3); + const inner = value.inner; + FfiConverterUInt64.writeIntoCursor(inner.sinceTs, c); + FfiConverterUInt64.writeIntoCursor(inner.firesAtTs, c); + FfiConverterString.writeIntoCursor(inner.lastError, c); + return; + } + case FfiKeepAlive_Tags.Expired: { + c.writeI32(4); + const inner = value.inner; + FfiConverterUInt64.writeIntoCursor(inner.sinceTs, c); + return; + } + case FfiKeepAlive_Tags.Unavailable: { + c.writeI32(5); + const inner = value.inner; + FfiConverterBool.writeIntoCursor(inner.permanent, c); + FfiConverterOptionalUInt64.writeIntoCursor(inner.nextProbeTs, c); + return; + } + default: + // Throwing from here means that FfiKeepAlive_Tags hasn't matched an ordinal. + throw new UniffiInternalError.UnexpectedEnumCase(); + } + } + allocationSize(value: TypeName): number { + switch (value.tag) { + case FfiKeepAlive_Tags.Armed: { + const inner = value.inner; + let size = 4; + size += FfiConverterUInt64.allocationSize(inner.delayMs); + size += FfiConverterUInt64.allocationSize(inner.lastRestartTs); + size += FfiConverterUInt64.allocationSize(inner.firesAtTs); + return size; + } + case FfiKeepAlive_Tags.Delegated: { + const inner = value.inner; + let size = 4; + size += FfiConverterUInt64.allocationSize(inner.delegatedAtTs); + size += FfiConverterUInt64.allocationSize(inner.earliestFireTs); + return size; + } + case FfiKeepAlive_Tags.RestartFailing: { + const inner = value.inner; + let size = 4; + size += FfiConverterUInt64.allocationSize(inner.sinceTs); + size += FfiConverterUInt64.allocationSize(inner.firesAtTs); + size += FfiConverterString.allocationSize(inner.lastError); + return size; + } + case FfiKeepAlive_Tags.Expired: { + const inner = value.inner; + let size = 4; + size += FfiConverterUInt64.allocationSize(inner.sinceTs); + return size; + } + case FfiKeepAlive_Tags.Unavailable: { + const inner = value.inner; + let size = 4; + size += FfiConverterBool.allocationSize(inner.permanent); + size += FfiConverterOptionalUInt64.allocationSize(inner.nextProbeTs); + return size; + } + default: throw new UniffiInternalError.UnexpectedEnumCase(); + } + } + } + return new FFIConverter(); +})(); + + +// Enum: FfiRosterPresence +export enum FfiRosterPresence_Tags { + AwaitingEcho = "AwaitingEcho", + Present = "Present", + Missing = "Missing", + Excluded = "Excluded" +} +/** + * Whether the session projects our own membership — i.e. whether anybody + * can see us. + */ +export const FfiRosterPresence = (() => { + + type AwaitingEcho__interface = { + tag: FfiRosterPresence_Tags.AwaitingEcho + }; + /** + * Sent, echo not back yet. Not a fault. + */ + class AwaitingEcho_ extends UniffiEnum implements AwaitingEcho__interface { + /** + * @private + * This field is private and should not be used, use `tag` instead. + */ + readonly [uniffiTypeNameSymbol] = "FfiRosterPresence"; + readonly tag = FfiRosterPresence_Tags.AwaitingEcho; + constructor() { + super("FfiRosterPresence", "AwaitingEcho"); + } + + static new(): AwaitingEcho_ { + return new AwaitingEcho_(); + } + + static instanceOf(obj: any): obj is AwaitingEcho_ { + return obj.tag === FfiRosterPresence_Tags.AwaitingEcho; + } + + } + + type Present__interface = { + tag: FfiRosterPresence_Tags.Present + }; + class Present_ extends UniffiEnum implements Present__interface { + /** + * @private + * This field is private and should not be used, use `tag` instead. + */ + readonly [uniffiTypeNameSymbol] = "FfiRosterPresence"; + readonly tag = FfiRosterPresence_Tags.Present; + constructor() { + super("FfiRosterPresence", "Present"); + } + + static new(): Present_ { + return new Present_(); + } + + static instanceOf(obj: any): obj is Present_ { + return obj.tag === FfiRosterPresence_Tags.Present; + } + + } + + type Missing__interface = { + tag: FfiRosterPresence_Tags.Missing; + inner: +Readonly<{sinceTs: bigint; republishedAtTs?: bigint}> + }; + /** + * It was in the roster and is gone. + */ + class Missing_ extends UniffiEnum implements Missing__interface { + /** + * @private + * This field is private and should not be used, use `tag` instead. + */ + readonly [uniffiTypeNameSymbol] = "FfiRosterPresence"; + readonly tag = FfiRosterPresence_Tags.Missing; + readonly inner: +Readonly<{sinceTs: bigint; republishedAtTs?: bigint}>; + constructor( +inner: {sinceTs: bigint; republishedAtTs?: bigint }) { + super("FfiRosterPresence", "Missing"); + + this.inner = Object.freeze(inner); + } + static new( +inner: {sinceTs: bigint; republishedAtTs?: bigint }): Missing_ { + return new Missing_(inner); + } + + static instanceOf(obj: any): obj is Missing_ { + return obj.tag === FfiRosterPresence_Tags.Missing; + } + + } + + type Excluded__interface = { + tag: FfiRosterPresence_Tags.Excluded; + inner: +Readonly<{reason: FfiJoinExclusionReason}> + }; + /** + * On the server, but the session refuses to project it. The self-heal + * deliberately does not re-send here. + */ + class Excluded_ extends UniffiEnum implements Excluded__interface { + /** + * @private + * This field is private and should not be used, use `tag` instead. + */ + readonly [uniffiTypeNameSymbol] = "FfiRosterPresence"; + readonly tag = FfiRosterPresence_Tags.Excluded; + readonly inner: +Readonly<{reason: FfiJoinExclusionReason}>; + constructor( +inner: {reason: FfiJoinExclusionReason }) { + super("FfiRosterPresence", "Excluded"); + + this.inner = Object.freeze(inner); + } + static new( +inner: {reason: FfiJoinExclusionReason }): Excluded_ { + return new Excluded_(inner); + } + + static instanceOf(obj: any): obj is Excluded_ { + return obj.tag === FfiRosterPresence_Tags.Excluded; + } + + } + + function instanceOf(obj: any): obj is FfiRosterPresence { + return obj[uniffiTypeNameSymbol] === "FfiRosterPresence"; + } + + return Object.freeze({ + instanceOf, + AwaitingEcho: AwaitingEcho_, + Present: Present_, + Missing: Missing_, + Excluded: Excluded_ + }); + +})(); +/** + * Whether the session projects our own membership — i.e. whether anybody + * can see us. + */ +export type FfiRosterPresence = InstanceType< + typeof FfiRosterPresence['AwaitingEcho' | 'Present' | 'Missing' | 'Excluded'] +>; + +// FfiConverter for enum FfiRosterPresence +const FfiConverterTypeFfiRosterPresence = (() => { + type TypeName = FfiRosterPresence; + class FFIConverter extends AbstractFfiConverterByteArray { + readFromCursor(c: Cursor): TypeName { + switch (c.readI32()) { + case 1: return new FfiRosterPresence.AwaitingEcho(); + case 2: return new FfiRosterPresence.Present(); + case 3: return new FfiRosterPresence.Missing({sinceTs: FfiConverterUInt64.readFromCursor(c), republishedAtTs: FfiConverterOptionalUInt64.readFromCursor(c) }); + case 4: return new FfiRosterPresence.Excluded({reason: FfiConverterTypeFfiJoinExclusionReason.readFromCursor(c) }); + default: throw new UniffiInternalError.UnexpectedEnumCase(); + } + } + writeIntoCursor(value: TypeName, c: Cursor): void { + switch (value.tag) { + case FfiRosterPresence_Tags.AwaitingEcho: { + c.writeI32(1); + return; + } + case FfiRosterPresence_Tags.Present: { + c.writeI32(2); + return; + } + case FfiRosterPresence_Tags.Missing: { + c.writeI32(3); + const inner = value.inner; + FfiConverterUInt64.writeIntoCursor(inner.sinceTs, c); + FfiConverterOptionalUInt64.writeIntoCursor(inner.republishedAtTs, c); + return; + } + case FfiRosterPresence_Tags.Excluded: { + c.writeI32(4); + const inner = value.inner; + FfiConverterTypeFfiJoinExclusionReason.writeIntoCursor(inner.reason, c); + return; + } + default: + // Throwing from here means that FfiRosterPresence_Tags hasn't matched an ordinal. + throw new UniffiInternalError.UnexpectedEnumCase(); + } + } + allocationSize(value: TypeName): number { + switch (value.tag) { + case FfiRosterPresence_Tags.AwaitingEcho: { + return 4; + } + case FfiRosterPresence_Tags.Present: { + return 4; + } + case FfiRosterPresence_Tags.Missing: { + const inner = value.inner; + let size = 4; + size += FfiConverterUInt64.allocationSize(inner.sinceTs); + size += FfiConverterOptionalUInt64.allocationSize(inner.republishedAtTs); + return size; + } + case FfiRosterPresence_Tags.Excluded: { + const inner = value.inner; + let size = 4; + size += FfiConverterTypeFfiJoinExclusionReason.allocationSize(inner.reason); + return size; + } + default: throw new UniffiInternalError.UnexpectedEnumCase(); + } + } + } + return new FFIConverter(); +})(); + +/** + * How severe an [`FfiImpairment`] is, and therefore where to render it. + */ +export enum FfiSeverity { + /** + * We are, or are about to be, out of the call — or peers cannot use + * our media. + */ + Critical, + /** + * Degraded but functioning; a crash or a timeout would now hurt. + */ + Degraded, + /** + * Worth surfacing in diagnostics, not in the call UI. + */ + Notice +} + +const FfiConverterTypeFfiSeverity = (() => { + type TypeName = FfiSeverity; + class FFIConverter extends AbstractFfiConverterByteArray { + readFromCursor(c: Cursor): TypeName { + switch (c.readI32()) { + case 1: return FfiSeverity.Critical; + case 2: return FfiSeverity.Degraded; + case 3: return FfiSeverity.Notice; + default: throw new UniffiInternalError.UnexpectedEnumCase(); + } + } + writeIntoCursor(value: TypeName, c: Cursor): void { + switch (value) { + case FfiSeverity.Critical: return c.writeI32(1); + case FfiSeverity.Degraded: return c.writeI32(2); + case FfiSeverity.Notice: return c.writeI32(3); + } + } + allocationSize(value: TypeName): number { + return 4; + } + } + return new FFIConverter(); +})(); + + +// Enum: FfiStatus +export enum FfiStatus_Tags { + Disconnected = "Disconnected", + Joining = "Joining", + Connected = "Connected", + Leaving = "Leaving" +} +/** + * The participation status, in full. + * + * This used to be four opaque variants with everything else hidden behind + * `debug_snapshot`'s unversioned JSON — which is a diagnostics dump, not a + * UI contract. Every field a host needs is now typed. + */ +export const FfiStatus = (() => { + + type Disconnected__interface = { + tag: FfiStatus_Tags.Disconnected; + inner: +Readonly<{cause: FfiDisconnectCause}> + }; + class Disconnected_ extends UniffiEnum implements Disconnected__interface { + /** + * @private + * This field is private and should not be used, use `tag` instead. + */ + readonly [uniffiTypeNameSymbol] = "FfiStatus"; + readonly tag = FfiStatus_Tags.Disconnected; + readonly inner: +Readonly<{cause: FfiDisconnectCause}>; + constructor( +inner: {cause: FfiDisconnectCause }) { + super("FfiStatus", "Disconnected"); + + this.inner = Object.freeze(inner); + } + static new( +inner: {cause: FfiDisconnectCause }): Disconnected_ { + return new Disconnected_(inner); + } + + static instanceOf(obj: any): obj is Disconnected_ { + return obj.tag === FfiStatus_Tags.Disconnected; + } + + } + + type Joining__interface = { + tag: FfiStatus_Tags.Joining; + inner: +Readonly<{ownMembership: FfiJoinProgress; encryption: FfiEncryptionStatus; impairments: Array}> + }; + class Joining_ extends UniffiEnum implements Joining__interface { + /** + * @private + * This field is private and should not be used, use `tag` instead. + */ + readonly [uniffiTypeNameSymbol] = "FfiStatus"; + readonly tag = FfiStatus_Tags.Joining; + readonly inner: +Readonly<{ownMembership: FfiJoinProgress; encryption: FfiEncryptionStatus; impairments: Array}>; + constructor( +inner: {ownMembership: FfiJoinProgress; encryption: FfiEncryptionStatus; impairments: Array }) { + super("FfiStatus", "Joining"); + + this.inner = Object.freeze(inner); + } + static new( +inner: {ownMembership: FfiJoinProgress; encryption: FfiEncryptionStatus; impairments: Array }): Joining_ { + return new Joining_(inner); + } + + static instanceOf(obj: any): obj is Joining_ { + return obj.tag === FfiStatus_Tags.Joining; + } + + } + + type Connected__interface = { + tag: FfiStatus_Tags.Connected; + inner: +Readonly<{keepAlive: FfiKeepAlive; membership: FfiMembershipPublication; roster: FfiRosterPresence; encryption: FfiEncryptionStatus; impairments: Array}> + }; + class Connected_ extends UniffiEnum implements Connected__interface { + /** + * @private + * This field is private and should not be used, use `tag` instead. + */ + readonly [uniffiTypeNameSymbol] = "FfiStatus"; + readonly tag = FfiStatus_Tags.Connected; + readonly inner: +Readonly<{keepAlive: FfiKeepAlive; membership: FfiMembershipPublication; roster: FfiRosterPresence; encryption: FfiEncryptionStatus; impairments: Array}>; + constructor( +inner: {keepAlive: FfiKeepAlive; membership: FfiMembershipPublication; roster: FfiRosterPresence; encryption: FfiEncryptionStatus; impairments: Array }) { + super("FfiStatus", "Connected"); + + this.inner = Object.freeze(inner); + } + static new( +inner: {keepAlive: FfiKeepAlive; membership: FfiMembershipPublication; roster: FfiRosterPresence; encryption: FfiEncryptionStatus; impairments: Array }): Connected_ { + return new Connected_(inner); + } + + static instanceOf(obj: any): obj is Connected_ { + return obj.tag === FfiStatus_Tags.Connected; + } + + } + + type Leaving__interface = { + tag: FfiStatus_Tags.Leaving; + inner: +Readonly<{leaveEventSent: boolean; delayedLeave?: FfiDelayedLeaveOutcome; impairments: Array}> + }; + class Leaving_ extends UniffiEnum implements Leaving__interface { + /** + * @private + * This field is private and should not be used, use `tag` instead. + */ + readonly [uniffiTypeNameSymbol] = "FfiStatus"; + readonly tag = FfiStatus_Tags.Leaving; + readonly inner: +Readonly<{leaveEventSent: boolean; delayedLeave?: FfiDelayedLeaveOutcome; impairments: Array}>; + constructor( +inner: {leaveEventSent: boolean; delayedLeave?: FfiDelayedLeaveOutcome; impairments: Array }) { + super("FfiStatus", "Leaving"); + + this.inner = Object.freeze(inner); + } + static new( +inner: {leaveEventSent: boolean; delayedLeave?: FfiDelayedLeaveOutcome; impairments: Array }): Leaving_ { + return new Leaving_(inner); + } + + static instanceOf(obj: any): obj is Leaving_ { + return obj.tag === FfiStatus_Tags.Leaving; + } + + } + + function instanceOf(obj: any): obj is FfiStatus { + return obj[uniffiTypeNameSymbol] === "FfiStatus"; + } + + return Object.freeze({ + instanceOf, + Disconnected: Disconnected_, + Joining: Joining_, + Connected: Connected_, + Leaving: Leaving_ + }); + +})(); +/** + * The participation status, in full. + * + * This used to be four opaque variants with everything else hidden behind + * `debug_snapshot`'s unversioned JSON — which is a diagnostics dump, not a + * UI contract. Every field a host needs is now typed. + */ +export type FfiStatus = InstanceType< + typeof FfiStatus['Disconnected' | 'Joining' | 'Connected' | 'Leaving'] +>; + +// FfiConverter for enum FfiStatus +const FfiConverterTypeFfiStatus = (() => { + type TypeName = FfiStatus; + class FFIConverter extends AbstractFfiConverterByteArray { + readFromCursor(c: Cursor): TypeName { + switch (c.readI32()) { + case 1: return new FfiStatus.Disconnected({cause: FfiConverterTypeFfiDisconnectCause.readFromCursor(c) }); + case 2: return new FfiStatus.Joining({ownMembership: FfiConverterTypeFfiJoinProgress.readFromCursor(c), encryption: FfiConverterTypeFfiEncryptionStatus.readFromCursor(c), impairments: FfiConverterSequenceTypeFfiImpairment.readFromCursor(c) }); + case 3: return new FfiStatus.Connected({keepAlive: FfiConverterTypeFfiKeepAlive.readFromCursor(c), membership: FfiConverterTypeFfiMembershipPublication.readFromCursor(c), roster: FfiConverterTypeFfiRosterPresence.readFromCursor(c), encryption: FfiConverterTypeFfiEncryptionStatus.readFromCursor(c), impairments: FfiConverterSequenceTypeFfiImpairment.readFromCursor(c) }); + case 4: return new FfiStatus.Leaving({leaveEventSent: FfiConverterBool.readFromCursor(c), delayedLeave: FfiConverterOptionalTypeFfiDelayedLeaveOutcome.readFromCursor(c), impairments: FfiConverterSequenceTypeFfiImpairment.readFromCursor(c) }); + default: throw new UniffiInternalError.UnexpectedEnumCase(); + } + } + writeIntoCursor(value: TypeName, c: Cursor): void { + switch (value.tag) { + case FfiStatus_Tags.Disconnected: { + c.writeI32(1); + const inner = value.inner; + FfiConverterTypeFfiDisconnectCause.writeIntoCursor(inner.cause, c); + return; + } + case FfiStatus_Tags.Joining: { + c.writeI32(2); + const inner = value.inner; + FfiConverterTypeFfiJoinProgress.writeIntoCursor(inner.ownMembership, c); + FfiConverterTypeFfiEncryptionStatus.writeIntoCursor(inner.encryption, c); + FfiConverterSequenceTypeFfiImpairment.writeIntoCursor(inner.impairments, c); + return; + } + case FfiStatus_Tags.Connected: { + c.writeI32(3); + const inner = value.inner; + FfiConverterTypeFfiKeepAlive.writeIntoCursor(inner.keepAlive, c); + FfiConverterTypeFfiMembershipPublication.writeIntoCursor(inner.membership, c); + FfiConverterTypeFfiRosterPresence.writeIntoCursor(inner.roster, c); + FfiConverterTypeFfiEncryptionStatus.writeIntoCursor(inner.encryption, c); + FfiConverterSequenceTypeFfiImpairment.writeIntoCursor(inner.impairments, c); + return; + } + case FfiStatus_Tags.Leaving: { + c.writeI32(4); + const inner = value.inner; + FfiConverterBool.writeIntoCursor(inner.leaveEventSent, c); + FfiConverterOptionalTypeFfiDelayedLeaveOutcome.writeIntoCursor(inner.delayedLeave, c); + FfiConverterSequenceTypeFfiImpairment.writeIntoCursor(inner.impairments, c); + return; + } + default: + // Throwing from here means that FfiStatus_Tags hasn't matched an ordinal. + throw new UniffiInternalError.UnexpectedEnumCase(); + } + } + allocationSize(value: TypeName): number { + switch (value.tag) { + case FfiStatus_Tags.Disconnected: { + const inner = value.inner; + let size = 4; + size += FfiConverterTypeFfiDisconnectCause.allocationSize(inner.cause); + return size; + } + case FfiStatus_Tags.Joining: { + const inner = value.inner; + let size = 4; + size += FfiConverterTypeFfiJoinProgress.allocationSize(inner.ownMembership); + size += FfiConverterTypeFfiEncryptionStatus.allocationSize(inner.encryption); + size += FfiConverterSequenceTypeFfiImpairment.allocationSize(inner.impairments); + return size; + } + case FfiStatus_Tags.Connected: { + const inner = value.inner; + let size = 4; + size += FfiConverterTypeFfiKeepAlive.allocationSize(inner.keepAlive); + size += FfiConverterTypeFfiMembershipPublication.allocationSize(inner.membership); + size += FfiConverterTypeFfiRosterPresence.allocationSize(inner.roster); + size += FfiConverterTypeFfiEncryptionStatus.allocationSize(inner.encryption); + size += FfiConverterSequenceTypeFfiImpairment.allocationSize(inner.impairments); + return size; + } + case FfiStatus_Tags.Leaving: { + const inner = value.inner; + let size = 4; + size += FfiConverterBool.allocationSize(inner.leaveEventSent); + size += FfiConverterOptionalTypeFfiDelayedLeaveOutcome.allocationSize(inner.delayedLeave); + size += FfiConverterSequenceTypeFfiImpairment.allocationSize(inner.impairments); + return size; + } + default: throw new UniffiInternalError.UnexpectedEnumCase(); + } + } + } + return new FFIConverter(); +})(); + + +// Enum: FfiTransportIntent +export enum FfiTransportIntent_Tags { + Publish = "Publish", + ReceiveOnly = "ReceiveOnly" +} +export const FfiTransportIntent = (() => { + + type Publish__interface = { + tag: FfiTransportIntent_Tags.Publish; + inner: +Readonly<{transport: FfiRtcTransport}> + }; + class Publish_ extends UniffiEnum implements Publish__interface { + /** + * @private + * This field is private and should not be used, use `tag` instead. + */ + readonly [uniffiTypeNameSymbol] = "FfiTransportIntent"; + readonly tag = FfiTransportIntent_Tags.Publish; + readonly inner: +Readonly<{transport: FfiRtcTransport}>; + constructor( +inner: {transport: FfiRtcTransport }) { + super("FfiTransportIntent", "Publish"); + + this.inner = Object.freeze(inner); + } + static new( +inner: {transport: FfiRtcTransport }): Publish_ { + return new Publish_(inner); + } + + static instanceOf(obj: any): obj is Publish_ { + return obj.tag === FfiTransportIntent_Tags.Publish; + } + + } + + type ReceiveOnly__interface = { + tag: FfiTransportIntent_Tags.ReceiveOnly; + inner: +Readonly<{canSubscribe: Array}> + }; + class ReceiveOnly_ extends UniffiEnum implements ReceiveOnly__interface { + /** + * @private + * This field is private and should not be used, use `tag` instead. + */ + readonly [uniffiTypeNameSymbol] = "FfiTransportIntent"; + readonly tag = FfiTransportIntent_Tags.ReceiveOnly; + readonly inner: +Readonly<{canSubscribe: Array}>; + constructor( +inner: {canSubscribe: Array }) { + super("FfiTransportIntent", "ReceiveOnly"); + + this.inner = Object.freeze(inner); + } + static new( +inner: {canSubscribe: Array }): ReceiveOnly_ { + return new ReceiveOnly_(inner); + } + + static instanceOf(obj: any): obj is ReceiveOnly_ { + return obj.tag === FfiTransportIntent_Tags.ReceiveOnly; + } + + } + + function instanceOf(obj: any): obj is FfiTransportIntent { + return obj[uniffiTypeNameSymbol] === "FfiTransportIntent"; + } + + return Object.freeze({ + instanceOf, + Publish: Publish_, + ReceiveOnly: ReceiveOnly_ + }); + +})(); +export type FfiTransportIntent = InstanceType< + typeof FfiTransportIntent['Publish' | 'ReceiveOnly'] +>; + +// FfiConverter for enum FfiTransportIntent +const FfiConverterTypeFfiTransportIntent = (() => { + type TypeName = FfiTransportIntent; + class FFIConverter extends AbstractFfiConverterByteArray { + readFromCursor(c: Cursor): TypeName { + switch (c.readI32()) { + case 1: return new FfiTransportIntent.Publish({transport: FfiConverterTypeFfiRtcTransport.readFromCursor(c) }); + case 2: return new FfiTransportIntent.ReceiveOnly({canSubscribe: FfiConverterSequenceString.readFromCursor(c) }); + default: throw new UniffiInternalError.UnexpectedEnumCase(); + } + } + writeIntoCursor(value: TypeName, c: Cursor): void { + switch (value.tag) { + case FfiTransportIntent_Tags.Publish: { + c.writeI32(1); + const inner = value.inner; + FfiConverterTypeFfiRtcTransport.writeIntoCursor(inner.transport, c); + return; + } + case FfiTransportIntent_Tags.ReceiveOnly: { + c.writeI32(2); + const inner = value.inner; + FfiConverterSequenceString.writeIntoCursor(inner.canSubscribe, c); + return; + } + default: + // Throwing from here means that FfiTransportIntent_Tags hasn't matched an ordinal. + throw new UniffiInternalError.UnexpectedEnumCase(); + } + } + allocationSize(value: TypeName): number { + switch (value.tag) { + case FfiTransportIntent_Tags.Publish: { + const inner = value.inner; + let size = 4; + size += FfiConverterTypeFfiRtcTransport.allocationSize(inner.transport); + return size; + } + case FfiTransportIntent_Tags.ReceiveOnly: { + const inner = value.inner; + let size = 4; + size += FfiConverterSequenceString.allocationSize(inner.canSubscribe); + return size; + } + default: throw new UniffiInternalError.UnexpectedEnumCase(); + } + } + } + return new FFIConverter(); +})(); + + +// Error type: RtcError +export enum RtcError_Tags { + InvalidInput = "InvalidInput", + Http = "Http", + Driver = "Driver", + Rejected = "Rejected", + Unsupported = "Unsupported", + RateLimited = "RateLimited", + Stopped = "Stopped", + AlreadyJoined = "AlreadyJoined", + NotJoined = "NotJoined", + SlotClosed = "SlotClosed", + NoTransport = "NoTransport", + TokenRefused = "TokenRefused", + EncryptionSetup = "EncryptionSetup" +} +/** + * Errors across the FFI, both directions. A foreign driver maps its + * homeserver errors onto these: `Rejected` = 403 `M_FORBIDDEN`, + * `Unsupported` = 404 `M_UNRECOGNIZED` — both read as "this homeserver will + * never do delayed events" by the own-membership machine. + */ +export const RtcError = (() => { + + type InvalidInput__interface = { + tag: RtcError_Tags.InvalidInput; + inner: +Readonly< +[string +]> + }; + class InvalidInput_ extends UniffiError implements InvalidInput__interface { + /** + * @private + * This field is private and should not be used, use `tag` instead. + */ + readonly [uniffiTypeNameSymbol] = "RtcError"; + readonly tag = RtcError_Tags.InvalidInput; + readonly inner: +Readonly< +[string +]>; + constructor(v0: string) { + super("RtcError", "InvalidInput"); + + this.inner = Object.freeze([v0]); + } + static new(v0: string): InvalidInput_ { + return new InvalidInput_(v0); + } + + static instanceOf(obj: any): obj is InvalidInput_ { + return obj.tag === RtcError_Tags.InvalidInput; + } + static hasInner(obj: any): obj is InvalidInput_ { + return InvalidInput_.instanceOf(obj); + } + + static getInner(obj: InvalidInput_): +Readonly< +[string +]> { + return obj.inner; + } + + } + + type Http__interface = { + tag: RtcError_Tags.Http; + inner: +Readonly< +[string +]> + }; + /** + * A homeserver HTTP failure — transient as far as this crate knows. + */ + class Http_ extends UniffiError implements Http__interface { + /** + * @private + * This field is private and should not be used, use `tag` instead. + */ + readonly [uniffiTypeNameSymbol] = "RtcError"; + readonly tag = RtcError_Tags.Http; + readonly inner: +Readonly< +[string +]>; + constructor(v0: string) { + super("RtcError", "Http"); + + this.inner = Object.freeze([v0]); + } + static new(v0: string): Http_ { + return new Http_(v0); + } + + static instanceOf(obj: any): obj is Http_ { + return obj.tag === RtcError_Tags.Http; + } + static hasInner(obj: any): obj is Http_ { + return Http_.instanceOf(obj); + } + + static getInner(obj: Http_): +Readonly< +[string +]> { + return obj.inner; + } + + } + + type Driver__interface = { + tag: RtcError_Tags.Driver; + inner: +Readonly< +[string +]> + }; + /** + * Anything the driver could not classify. + */ + class Driver_ extends UniffiError implements Driver__interface { + /** + * @private + * This field is private and should not be used, use `tag` instead. + */ + readonly [uniffiTypeNameSymbol] = "RtcError"; + readonly tag = RtcError_Tags.Driver; + readonly inner: +Readonly< +[string +]>; + constructor(v0: string) { + super("RtcError", "Driver"); + + this.inner = Object.freeze([v0]); + } + static new(v0: string): Driver_ { + return new Driver_(v0); + } + + static instanceOf(obj: any): obj is Driver_ { + return obj.tag === RtcError_Tags.Driver; + } + static hasInner(obj: any): obj is Driver_ { + return Driver_.instanceOf(obj); + } + + static getInner(obj: Driver_): +Readonly< +[string +]> { + return obj.inner; + } + + } + + type Rejected__interface = { + tag: RtcError_Tags.Rejected; + inner: +Readonly< +[string +]> + }; + class Rejected_ extends UniffiError implements Rejected__interface { + /** + * @private + * This field is private and should not be used, use `tag` instead. + */ + readonly [uniffiTypeNameSymbol] = "RtcError"; + readonly tag = RtcError_Tags.Rejected; + readonly inner: +Readonly< +[string +]>; + constructor(v0: string) { + super("RtcError", "Rejected"); + + this.inner = Object.freeze([v0]); + } + static new(v0: string): Rejected_ { + return new Rejected_(v0); + } + + static instanceOf(obj: any): obj is Rejected_ { + return obj.tag === RtcError_Tags.Rejected; + } + static hasInner(obj: any): obj is Rejected_ { + return Rejected_.instanceOf(obj); + } + + static getInner(obj: Rejected_): +Readonly< +[string +]> { + return obj.inner; + } + + } + + type Unsupported__interface = { + tag: RtcError_Tags.Unsupported; + inner: +Readonly< +[string +]> + }; + class Unsupported_ extends UniffiError implements Unsupported__interface { + /** + * @private + * This field is private and should not be used, use `tag` instead. + */ + readonly [uniffiTypeNameSymbol] = "RtcError"; + readonly tag = RtcError_Tags.Unsupported; + readonly inner: +Readonly< +[string +]>; + constructor(v0: string) { + super("RtcError", "Unsupported"); + + this.inner = Object.freeze([v0]); + } + static new(v0: string): Unsupported_ { + return new Unsupported_(v0); + } + + static instanceOf(obj: any): obj is Unsupported_ { + return obj.tag === RtcError_Tags.Unsupported; + } + static hasInner(obj: any): obj is Unsupported_ { + return Unsupported_.instanceOf(obj); + } + + static getInner(obj: Unsupported_): +Readonly< +[string +]> { + return obj.inner; + } + + } + + type RateLimited__interface = { + tag: RtcError_Tags.RateLimited; + inner: +Readonly<{retryAfterMs?: bigint}> + }; + /** + * `M_LIMIT_EXCEEDED`: back off for `retry_after_ms` before retrying. + */ + class RateLimited_ extends UniffiError implements RateLimited__interface { + /** + * @private + * This field is private and should not be used, use `tag` instead. + */ + readonly [uniffiTypeNameSymbol] = "RtcError"; + readonly tag = RtcError_Tags.RateLimited; + readonly inner: +Readonly<{retryAfterMs?: bigint}>; + constructor( +inner: {retryAfterMs?: bigint }) { + super("RtcError", "RateLimited"); + + this.inner = Object.freeze(inner); + } + static new( +inner: {retryAfterMs?: bigint }): RateLimited_ { + return new RateLimited_(inner); + } + + static instanceOf(obj: any): obj is RateLimited_ { + return obj.tag === RtcError_Tags.RateLimited; + } + static hasInner(obj: any): obj is RateLimited_ { + return RateLimited_.instanceOf(obj); + } + + static getInner(obj: RateLimited_): +Readonly<{retryAfterMs?: bigint}> { + return obj.inner; + } + + } + + type Stopped__interface = { + tag: RtcError_Tags.Stopped + }; + /** + * The manager behind the call has stopped; build a new one. + */ + class Stopped_ extends UniffiError implements Stopped__interface { + /** + * @private + * This field is private and should not be used, use `tag` instead. + */ + readonly [uniffiTypeNameSymbol] = "RtcError"; + readonly tag = RtcError_Tags.Stopped; + constructor() { + super("RtcError", "Stopped"); + } + + static new(): Stopped_ { + return new Stopped_(); + } + + static instanceOf(obj: any): obj is Stopped_ { + return obj.tag === RtcError_Tags.Stopped; + } + static hasInner(obj: any): obj is Stopped_ { + return false; + } + + } + + type AlreadyJoined__interface = { + tag: RtcError_Tags.AlreadyJoined + }; + class AlreadyJoined_ extends UniffiError implements AlreadyJoined__interface { + /** + * @private + * This field is private and should not be used, use `tag` instead. + */ + readonly [uniffiTypeNameSymbol] = "RtcError"; + readonly tag = RtcError_Tags.AlreadyJoined; + constructor() { + super("RtcError", "AlreadyJoined"); + } + + static new(): AlreadyJoined_ { + return new AlreadyJoined_(); + } + + static instanceOf(obj: any): obj is AlreadyJoined_ { + return obj.tag === RtcError_Tags.AlreadyJoined; + } + static hasInner(obj: any): obj is AlreadyJoined_ { + return false; + } + + } + + type NotJoined__interface = { + tag: RtcError_Tags.NotJoined + }; + class NotJoined_ extends UniffiError implements NotJoined__interface { + /** + * @private + * This field is private and should not be used, use `tag` instead. + */ + readonly [uniffiTypeNameSymbol] = "RtcError"; + readonly tag = RtcError_Tags.NotJoined; + constructor() { + super("RtcError", "NotJoined"); + } + + static new(): NotJoined_ { + return new NotJoined_(); + } + + static instanceOf(obj: any): obj is NotJoined_ { + return obj.tag === RtcError_Tags.NotJoined; + } + static hasInner(obj: any): obj is NotJoined_ { + return false; + } + + } + + type SlotClosed__interface = { + tag: RtcError_Tags.SlotClosed + }; + class SlotClosed_ extends UniffiError implements SlotClosed__interface { + /** + * @private + * This field is private and should not be used, use `tag` instead. + */ + readonly [uniffiTypeNameSymbol] = "RtcError"; + readonly tag = RtcError_Tags.SlotClosed; + constructor() { + super("RtcError", "SlotClosed"); + } + + static new(): SlotClosed_ { + return new SlotClosed_(); + } + + static instanceOf(obj: any): obj is SlotClosed_ { + return obj.tag === RtcError_Tags.SlotClosed; + } + static hasInner(obj: any): obj is SlotClosed_ { + return false; + } + + } + + type NoTransport__interface = { + tag: RtcError_Tags.NoTransport; + inner: +Readonly< +[string +]> + }; + /** + * The homeserver advertises no usable RTC transport — a configuration + * problem; retrying will not help. + */ + class NoTransport_ extends UniffiError implements NoTransport__interface { + /** + * @private + * This field is private and should not be used, use `tag` instead. + */ + readonly [uniffiTypeNameSymbol] = "RtcError"; + readonly tag = RtcError_Tags.NoTransport; + readonly inner: +Readonly< +[string +]>; + constructor(v0: string) { + super("RtcError", "NoTransport"); + + this.inner = Object.freeze([v0]); + } + static new(v0: string): NoTransport_ { + return new NoTransport_(v0); + } + + static instanceOf(obj: any): obj is NoTransport_ { + return obj.tag === RtcError_Tags.NoTransport; + } + static hasInner(obj: any): obj is NoTransport_ { + return NoTransport_.instanceOf(obj); + } + + static getInner(obj: NoTransport_): +Readonly< +[string +]> { + return obj.inner; + } + + } + + type TokenRefused__interface = { + tag: RtcError_Tags.TokenRefused; + inner: +Readonly< +[string +]> + }; + /** + * A transport exists but its token could not be minted — auth or + * network; retrying may help. + */ + class TokenRefused_ extends UniffiError implements TokenRefused__interface { + /** + * @private + * This field is private and should not be used, use `tag` instead. + */ + readonly [uniffiTypeNameSymbol] = "RtcError"; + readonly tag = RtcError_Tags.TokenRefused; + readonly inner: +Readonly< +[string +]>; + constructor(v0: string) { + super("RtcError", "TokenRefused"); + + this.inner = Object.freeze([v0]); + } + static new(v0: string): TokenRefused_ { + return new TokenRefused_(v0); + } + + static instanceOf(obj: any): obj is TokenRefused_ { + return obj.tag === RtcError_Tags.TokenRefused; + } + static hasInner(obj: any): obj is TokenRefused_ { + return TokenRefused_.instanceOf(obj); + } + + static getInner(obj: TokenRefused_): +Readonly< +[string +]> { + return obj.inner; + } + + } + + type EncryptionSetup__interface = { + tag: RtcError_Tags.EncryptionSetup; + inner: +Readonly< +[string +]> + }; + /** + * A crate precondition, not a caller mistake. + */ + class EncryptionSetup_ extends UniffiError implements EncryptionSetup__interface { + /** + * @private + * This field is private and should not be used, use `tag` instead. + */ + readonly [uniffiTypeNameSymbol] = "RtcError"; + readonly tag = RtcError_Tags.EncryptionSetup; + readonly inner: +Readonly< +[string +]>; + constructor(v0: string) { + super("RtcError", "EncryptionSetup"); + + this.inner = Object.freeze([v0]); + } + static new(v0: string): EncryptionSetup_ { + return new EncryptionSetup_(v0); + } + + static instanceOf(obj: any): obj is EncryptionSetup_ { + return obj.tag === RtcError_Tags.EncryptionSetup; + } + static hasInner(obj: any): obj is EncryptionSetup_ { + return EncryptionSetup_.instanceOf(obj); + } + + static getInner(obj: EncryptionSetup_): +Readonly< +[string +]> { + return obj.inner; + } + + } + + function instanceOf(obj: any): obj is RtcError { + return obj[uniffiTypeNameSymbol] === "RtcError"; + } + + return Object.freeze({ + instanceOf, + InvalidInput: InvalidInput_, + Http: Http_, + Driver: Driver_, + Rejected: Rejected_, + Unsupported: Unsupported_, + RateLimited: RateLimited_, + Stopped: Stopped_, + AlreadyJoined: AlreadyJoined_, + NotJoined: NotJoined_, + SlotClosed: SlotClosed_, + NoTransport: NoTransport_, + TokenRefused: TokenRefused_, + EncryptionSetup: EncryptionSetup_ + }); + +})(); +/** + * Errors across the FFI, both directions. A foreign driver maps its + * homeserver errors onto these: `Rejected` = 403 `M_FORBIDDEN`, + * `Unsupported` = 404 `M_UNRECOGNIZED` — both read as "this homeserver will + * never do delayed events" by the own-membership machine. + */ +export type RtcError = InstanceType< + typeof RtcError['InvalidInput' | 'Http' | 'Driver' | 'Rejected' | 'Unsupported' | 'RateLimited' | 'Stopped' | 'AlreadyJoined' | 'NotJoined' | 'SlotClosed' | 'NoTransport' | 'TokenRefused' | 'EncryptionSetup'] +>; + +// FfiConverter for enum RtcError +const FfiConverterTypeRtcError = (() => { + type TypeName = RtcError; + class FFIConverter extends AbstractFfiConverterByteArray { + readFromCursor(c: Cursor): TypeName { + switch (c.readI32()) { + case 1: return new RtcError.InvalidInput(FfiConverterString.readFromCursor(c)); + case 2: return new RtcError.Http(FfiConverterString.readFromCursor(c)); + case 3: return new RtcError.Driver(FfiConverterString.readFromCursor(c)); + case 4: return new RtcError.Rejected(FfiConverterString.readFromCursor(c)); + case 5: return new RtcError.Unsupported(FfiConverterString.readFromCursor(c)); + case 6: return new RtcError.RateLimited({retryAfterMs: FfiConverterOptionalUInt64.readFromCursor(c) }); + case 7: return new RtcError.Stopped(); + case 8: return new RtcError.AlreadyJoined(); + case 9: return new RtcError.NotJoined(); + case 10: return new RtcError.SlotClosed(); + case 11: return new RtcError.NoTransport(FfiConverterString.readFromCursor(c)); + case 12: return new RtcError.TokenRefused(FfiConverterString.readFromCursor(c)); + case 13: return new RtcError.EncryptionSetup(FfiConverterString.readFromCursor(c)); + default: throw new UniffiInternalError.UnexpectedEnumCase(); + } + } + writeIntoCursor(value: TypeName, c: Cursor): void { + switch (value.tag) { + case RtcError_Tags.InvalidInput: { + c.writeI32(1); + const inner = value.inner; + FfiConverterString.writeIntoCursor(inner[0], c); + return; + } + case RtcError_Tags.Http: { + c.writeI32(2); + const inner = value.inner; + FfiConverterString.writeIntoCursor(inner[0], c); + return; + } + case RtcError_Tags.Driver: { + c.writeI32(3); + const inner = value.inner; + FfiConverterString.writeIntoCursor(inner[0], c); + return; + } + case RtcError_Tags.Rejected: { + c.writeI32(4); + const inner = value.inner; + FfiConverterString.writeIntoCursor(inner[0], c); + return; + } + case RtcError_Tags.Unsupported: { + c.writeI32(5); + const inner = value.inner; + FfiConverterString.writeIntoCursor(inner[0], c); + return; + } + case RtcError_Tags.RateLimited: { + c.writeI32(6); + const inner = value.inner; + FfiConverterOptionalUInt64.writeIntoCursor(inner.retryAfterMs, c); + return; + } + case RtcError_Tags.Stopped: { + c.writeI32(7); + return; + } + case RtcError_Tags.AlreadyJoined: { + c.writeI32(8); + return; + } + case RtcError_Tags.NotJoined: { + c.writeI32(9); + return; + } + case RtcError_Tags.SlotClosed: { + c.writeI32(10); + return; + } + case RtcError_Tags.NoTransport: { + c.writeI32(11); + const inner = value.inner; + FfiConverterString.writeIntoCursor(inner[0], c); + return; + } + case RtcError_Tags.TokenRefused: { + c.writeI32(12); + const inner = value.inner; + FfiConverterString.writeIntoCursor(inner[0], c); + return; + } + case RtcError_Tags.EncryptionSetup: { + c.writeI32(13); + const inner = value.inner; + FfiConverterString.writeIntoCursor(inner[0], c); + return; + } + default: + // Throwing from here means that RtcError_Tags hasn't matched an ordinal. + throw new UniffiInternalError.UnexpectedEnumCase(); + } + } + allocationSize(value: TypeName): number { + switch (value.tag) { + case RtcError_Tags.InvalidInput: { + const inner = value.inner; + let size = 4; + size += FfiConverterString.allocationSize(inner[0]); + return size; + } + case RtcError_Tags.Http: { + const inner = value.inner; + let size = 4; + size += FfiConverterString.allocationSize(inner[0]); + return size; + } + case RtcError_Tags.Driver: { + const inner = value.inner; + let size = 4; + size += FfiConverterString.allocationSize(inner[0]); + return size; + } + case RtcError_Tags.Rejected: { + const inner = value.inner; + let size = 4; + size += FfiConverterString.allocationSize(inner[0]); + return size; + } + case RtcError_Tags.Unsupported: { + const inner = value.inner; + let size = 4; + size += FfiConverterString.allocationSize(inner[0]); + return size; + } + case RtcError_Tags.RateLimited: { + const inner = value.inner; + let size = 4; + size += FfiConverterOptionalUInt64.allocationSize(inner.retryAfterMs); + return size; + } + case RtcError_Tags.Stopped: { + return 4; + } + case RtcError_Tags.AlreadyJoined: { + return 4; + } + case RtcError_Tags.NotJoined: { + return 4; + } + case RtcError_Tags.SlotClosed: { + return 4; + } + case RtcError_Tags.NoTransport: { + const inner = value.inner; + let size = 4; + size += FfiConverterString.allocationSize(inner[0]); + return size; + } + case RtcError_Tags.TokenRefused: { + const inner = value.inner; + let size = 4; + size += FfiConverterString.allocationSize(inner[0]); + return size; + } + case RtcError_Tags.EncryptionSetup: { + const inner = value.inner; + let size = 4; + size += FfiConverterString.allocationSize(inner[0]); + return size; + } + default: throw new UniffiInternalError.UnexpectedEnumCase(); + } + } + } + return new FFIConverter(); +})(); + +export interface ConnectionsListener { + + onConnectionsChange(connections: Array): void; +} + + +export class ConnectionsListenerImpl extends UniffiAbstractObject implements ConnectionsListener { + + readonly [uniffiTypeNameSymbol] = "ConnectionsListenerImpl"; + readonly [destructorGuardSymbol]: UniffiGcObject; + readonly [pointerLiteralSymbol]: UniffiHandle; + // No primary constructor declared for this class. +private constructor(pointer: UniffiHandle) { + super(); + this[pointerLiteralSymbol] = pointer; + this[destructorGuardSymbol] = uniffiTypeConnectionsListenerImplObjectFactory.bless(pointer); +} + + + + + onConnectionsChange(connections: Array): void {uniffiCaller.rustCall( + /*caller:*/ (callStatus) => { nativeModule().ubrn_uniffi_matrix_rtc_fn_method_connectionslistener_on_connections_change( + uniffiTypeConnectionsListenerImplObjectFactory.clonePointer(this), + FfiConverterSequenceTypeFfiConnectionWithMembers.lower(connections, nativeModule().rustbuffer_alloc), + callStatus); + }, + /*liftString:*/ FfiConverterString.lift.bind(FfiConverterString), + ); + } + + + uniffiDestroy(): void { + const ptr = (this as any)[destructorGuardSymbol]; + if (ptr !== undefined) { + const pointer = uniffiTypeConnectionsListenerImplObjectFactory.pointer(this); + uniffiTypeConnectionsListenerImplObjectFactory.freePointer(pointer); + uniffiTypeConnectionsListenerImplObjectFactory.unbless(ptr); + delete (this as any)[destructorGuardSymbol]; + } + } + + static instanceOf(obj_: any): obj_ is ConnectionsListenerImpl { + return uniffiTypeConnectionsListenerImplObjectFactory.isConcreteType(obj_); + } + + +} + +const uniffiTypeConnectionsListenerImplObjectFactory: UniffiObjectFactory = (() => { + + /// + const registry = typeof FinalizationRegistry !== 'undefined' ? new FinalizationRegistry((heldValue: UniffiHandle) => { + uniffiTypeConnectionsListenerImplObjectFactory.freePointer(heldValue); + }) : null; + + return { + create(pointer: UniffiHandle): ConnectionsListener { + const instance = Object.create(ConnectionsListenerImpl.prototype); + instance[pointerLiteralSymbol] = pointer; + instance[destructorGuardSymbol] = this.bless(pointer); + instance[uniffiTypeNameSymbol] = "ConnectionsListenerImpl"; + return instance; + }, + + + bless(p: UniffiHandle): UniffiGcObject { + const ptr = { + p, // make sure this object doesn't get optimized away. + markDestroyed: () => undefined, + }; + if (registry) { + registry.register(ptr, p, ptr); + } + return ptr; + }, + + unbless(ptr_: UniffiGcObject) { + if (registry) { + registry.unregister(ptr_); + } + }, + + pointer(obj_: ConnectionsListener): UniffiHandle { + if ((obj_ as any)[destructorGuardSymbol] === undefined) { + throw new UniffiInternalError.UnexpectedNullPointer(); + } + return (obj_ as any)[pointerLiteralSymbol]; + }, + + clonePointer(obj_: ConnectionsListener): UniffiHandle { + const pointer = this.pointer(obj_); + return uniffiCaller.rustCall( + /*caller:*/ (callStatus) => nativeModule().ubrn_uniffi_matrix_rtc_fn_clone_connectionslistener(pointer, callStatus), + /*liftString:*/ FfiConverterString.lift + ); + }, + + freePointer(pointer: UniffiHandle): void { + uniffiCaller.rustCall( + /*caller:*/ (callStatus) => nativeModule().ubrn_uniffi_matrix_rtc_fn_free_connectionslistener(pointer, callStatus), + /*liftString:*/ FfiConverterString.lift + ); + }, + + isConcreteType(obj_: any): obj_ is ConnectionsListener { + return obj_[destructorGuardSymbol] && obj_[uniffiTypeNameSymbol] === "ConnectionsListenerImpl"; + }, +}})(); +const FfiConverterTypeConnectionsListener = new FfiConverterObjectWithCallbacks(uniffiTypeConnectionsListenerImplObjectFactory); + +// Add a vtable for the callbacks that go in ConnectionsListener. + +// Put the implementation in a struct so we don't pollute the top-level namespace +const uniffiCallbackInterfaceConnectionsListener: { vtable: any; register: () => void; } = { + // Create the VTable using a series of closures. + // ts automatically converts these into C callback functions. + vtable: { + on_connections_change: ( + uniffiHandle: bigint, + connections: Uint8Array,) => { + const uniffiMakeCall = + () + : void => { + const jsCallback = FfiConverterTypeConnectionsListener.lift(uniffiHandle); + return jsCallback.onConnectionsChange( + FfiConverterSequenceTypeFfiConnectionWithMembers.lift(connections) + ) + }; + const uniffiResult = UniffiResult.ready(); + const uniffiHandleSuccess = (obj: any) => {}; + const uniffiHandleError = (code: number, errBuf: UniffiByteArray) => { + UniffiResult.writeError(uniffiResult, code, errBuf); + }; + uniffiTraitInterfaceCall( + /*makeCall:*/ uniffiMakeCall, + /*handleSuccess:*/ uniffiHandleSuccess, + /*handleError:*/ uniffiHandleError, + /*lowerString:*/ FfiConverterString.lower.bind(FfiConverterString), + /*alloc:*/ nativeModule().rustbuffer_alloc, + ) + return uniffiResult; + }, + uniffi_free: (uniffiHandle: UniffiHandle): void => { + // this will throw a stale handle error if the handle isn't found. + FfiConverterTypeConnectionsListener.drop(uniffiHandle); + }, + uniffi_clone: (uniffiHandle: UniffiHandle): UniffiHandle => { + return FfiConverterTypeConnectionsListener.clone(uniffiHandle); + } + }, + register: () => {nativeModule().ubrn_uniffi_matrix_rtc_fn_init_callback_vtable_connectionslistener( + uniffiCallbackInterfaceConnectionsListener.vtable + ); + }, +}; + +/** + * One end of the driver's connectivity stream: the host emits the new + * verdict whenever its homeserver connection comes or goes (a syncing + * client: sync running or not). `false` from `emit` means no consumer is + * left — unhook the handler. + */ +export interface ConnectivitySinkLike { + + emit(connected: boolean): boolean; +} +/** + * @deprecated Use `ConnectivitySinkLike` instead. + */ +export type ConnectivitySinkInterface = ConnectivitySinkLike; + + +/** + * One end of the driver's connectivity stream: the host emits the new + * verdict whenever its homeserver connection comes or goes (a syncing + * client: sync running or not). `false` from `emit` means no consumer is + * left — unhook the handler. + */ +export class ConnectivitySink extends UniffiAbstractObject implements ConnectivitySinkLike { + + readonly [uniffiTypeNameSymbol] = "ConnectivitySink"; + readonly [destructorGuardSymbol]: UniffiGcObject; + readonly [pointerLiteralSymbol]: UniffiHandle; + // No primary constructor declared for this class. +private constructor(pointer: UniffiHandle) { + super(); + this[pointerLiteralSymbol] = pointer; + this[destructorGuardSymbol] = uniffiTypeConnectivitySinkObjectFactory.bless(pointer); +} + + + + + emit(connected: boolean): boolean { + return FfiConverterBool.lift(uniffiCaller.rustCall( + /*caller:*/ (callStatus) => { + return nativeModule().ubrn_uniffi_matrix_rtc_fn_method_connectivitysink_emit( + uniffiTypeConnectivitySinkObjectFactory.clonePointer(this), + FfiConverterBool.lower(connected, nativeModule().rustbuffer_alloc), + callStatus); + }, + /*liftString:*/ FfiConverterString.lift.bind(FfiConverterString), + )); + } + + + uniffiDestroy(): void { + const ptr = (this as any)[destructorGuardSymbol]; + if (ptr !== undefined) { + const pointer = uniffiTypeConnectivitySinkObjectFactory.pointer(this); + uniffiTypeConnectivitySinkObjectFactory.freePointer(pointer); + uniffiTypeConnectivitySinkObjectFactory.unbless(ptr); + delete (this as any)[destructorGuardSymbol]; + } + } + + static instanceOf(obj_: any): obj_ is ConnectivitySink { + return uniffiTypeConnectivitySinkObjectFactory.isConcreteType(obj_); + } + + +} + +const uniffiTypeConnectivitySinkObjectFactory: UniffiObjectFactory = (() => { + + /// + const registry = typeof FinalizationRegistry !== 'undefined' ? new FinalizationRegistry((heldValue: UniffiHandle) => { + uniffiTypeConnectivitySinkObjectFactory.freePointer(heldValue); + }) : null; + + return { + create(pointer: UniffiHandle): ConnectivitySinkLike { + const instance = Object.create(ConnectivitySink.prototype); + instance[pointerLiteralSymbol] = pointer; + instance[destructorGuardSymbol] = this.bless(pointer); + instance[uniffiTypeNameSymbol] = "ConnectivitySink"; + return instance; + }, + + + bless(p: UniffiHandle): UniffiGcObject { + const ptr = { + p, // make sure this object doesn't get optimized away. + markDestroyed: () => undefined, + }; + if (registry) { + registry.register(ptr, p, ptr); + } + return ptr; + }, + + unbless(ptr_: UniffiGcObject) { + if (registry) { + registry.unregister(ptr_); + } + }, + + pointer(obj_: ConnectivitySinkLike): UniffiHandle { + if ((obj_ as any)[destructorGuardSymbol] === undefined) { + throw new UniffiInternalError.UnexpectedNullPointer(); + } + return (obj_ as any)[pointerLiteralSymbol]; + }, + + clonePointer(obj_: ConnectivitySinkLike): UniffiHandle { + const pointer = this.pointer(obj_); + return uniffiCaller.rustCall( + /*caller:*/ (callStatus) => nativeModule().ubrn_uniffi_matrix_rtc_fn_clone_connectivitysink(pointer, callStatus), + /*liftString:*/ FfiConverterString.lift + ); + }, + + freePointer(pointer: UniffiHandle): void { + uniffiCaller.rustCall( + /*caller:*/ (callStatus) => nativeModule().ubrn_uniffi_matrix_rtc_fn_free_connectivitysink(pointer, callStatus), + /*liftString:*/ FfiConverterString.lift + ); + }, + + isConcreteType(obj_: any): obj_ is ConnectivitySinkLike { + return obj_[destructorGuardSymbol] && obj_[uniffiTypeNameSymbol] === "ConnectivitySink"; + }, +}})(); +const FfiConverterTypeConnectivitySink = new FfiConverterObject(uniffiTypeConnectivitySinkObjectFactory); + +/** + * The FFI driver object — the one place a foreign [`MatrixDriverCallback`] + * becomes a [`crate::driver::MatrixDriver`]. Room-scoped and room-lived, + * like matrix-rust-sdk's widget `MatrixDriver`: construct it once per room + * and share it across managers (one room can hold several slots). + * + * It is both the FFI handle *and* the adapter: the trait impls below + * translate JSON-string payloads and FFI records into the crate's driver + * types. The foreign `subscribe_*` handshake happens in [`Self::new`], each + * sink feeding one inbound channel; the Rust trait's `subscribe_*` methods + * (fresh receiver per call) are served by fanning those channels out + * internally — so any number of managers consume a foreign driver exactly + * like a native one. + */ +export interface FfiMatrixDriverLike { + +} +/** + * @deprecated Use `FfiMatrixDriverLike` instead. + */ +export type FfiMatrixDriverInterface = FfiMatrixDriverLike; + + +/** + * The FFI driver object — the one place a foreign [`MatrixDriverCallback`] + * becomes a [`crate::driver::MatrixDriver`]. Room-scoped and room-lived, + * like matrix-rust-sdk's widget `MatrixDriver`: construct it once per room + * and share it across managers (one room can hold several slots). + * + * It is both the FFI handle *and* the adapter: the trait impls below + * translate JSON-string payloads and FFI records into the crate's driver + * types. The foreign `subscribe_*` handshake happens in [`Self::new`], each + * sink feeding one inbound channel; the Rust trait's `subscribe_*` methods + * (fresh receiver per call) are served by fanning those channels out + * internally — so any number of managers consume a foreign driver exactly + * like a native one. + */ +export class FfiMatrixDriver extends UniffiAbstractObject implements FfiMatrixDriverLike { + + readonly [uniffiTypeNameSymbol] = "FfiMatrixDriver"; + readonly [destructorGuardSymbol]: UniffiGcObject; + readonly [pointerLiteralSymbol]: UniffiHandle; +/** + * Performs the `subscribe_*` handshake with the foreign driver + * (synchronously, exactly once). + */ + constructor(callback: MatrixDriverCallback) { + super(); + const pointer = + uniffiCaller.rustCall( + /*caller:*/ (callStatus) => { + return nativeModule().ubrn_uniffi_matrix_rtc_fn_constructor_ffimatrixdriver_new( + FfiConverterTypeMatrixDriverCallback.lower(callback, nativeModule().rustbuffer_alloc), + callStatus); + }, + /*liftString:*/ FfiConverterString.lift.bind(FfiConverterString), + ); + this[pointerLiteralSymbol] = pointer; + this[destructorGuardSymbol] = uniffiTypeFfiMatrixDriverObjectFactory.bless(pointer); + } + + + + + + uniffiDestroy(): void { + const ptr = (this as any)[destructorGuardSymbol]; + if (ptr !== undefined) { + const pointer = uniffiTypeFfiMatrixDriverObjectFactory.pointer(this); + uniffiTypeFfiMatrixDriverObjectFactory.freePointer(pointer); + uniffiTypeFfiMatrixDriverObjectFactory.unbless(ptr); + delete (this as any)[destructorGuardSymbol]; + } + } + + static instanceOf(obj_: any): obj_ is FfiMatrixDriver { + return uniffiTypeFfiMatrixDriverObjectFactory.isConcreteType(obj_); + } + + +} + +const uniffiTypeFfiMatrixDriverObjectFactory: UniffiObjectFactory = (() => { + + /// + const registry = typeof FinalizationRegistry !== 'undefined' ? new FinalizationRegistry((heldValue: UniffiHandle) => { + uniffiTypeFfiMatrixDriverObjectFactory.freePointer(heldValue); + }) : null; + + return { + create(pointer: UniffiHandle): FfiMatrixDriverLike { + const instance = Object.create(FfiMatrixDriver.prototype); + instance[pointerLiteralSymbol] = pointer; + instance[destructorGuardSymbol] = this.bless(pointer); + instance[uniffiTypeNameSymbol] = "FfiMatrixDriver"; + return instance; + }, + + + bless(p: UniffiHandle): UniffiGcObject { + const ptr = { + p, // make sure this object doesn't get optimized away. + markDestroyed: () => undefined, + }; + if (registry) { + registry.register(ptr, p, ptr); + } + return ptr; + }, + + unbless(ptr_: UniffiGcObject) { + if (registry) { + registry.unregister(ptr_); + } + }, + + pointer(obj_: FfiMatrixDriverLike): UniffiHandle { + if ((obj_ as any)[destructorGuardSymbol] === undefined) { + throw new UniffiInternalError.UnexpectedNullPointer(); + } + return (obj_ as any)[pointerLiteralSymbol]; + }, + + clonePointer(obj_: FfiMatrixDriverLike): UniffiHandle { + const pointer = this.pointer(obj_); + return uniffiCaller.rustCall( + /*caller:*/ (callStatus) => nativeModule().ubrn_uniffi_matrix_rtc_fn_clone_ffimatrixdriver(pointer, callStatus), + /*liftString:*/ FfiConverterString.lift + ); + }, + + freePointer(pointer: UniffiHandle): void { + uniffiCaller.rustCall( + /*caller:*/ (callStatus) => nativeModule().ubrn_uniffi_matrix_rtc_fn_free_ffimatrixdriver(pointer, callStatus), + /*liftString:*/ FfiConverterString.lift + ); + }, + + isConcreteType(obj_: any): obj_ is FfiMatrixDriverLike { + return obj_[destructorGuardSymbol] && obj_[uniffiTypeNameSymbol] === "FfiMatrixDriver"; + }, +}})(); +const FfiConverterTypeFfiMatrixDriver = new FfiConverterObject(uniffiTypeFfiMatrixDriverObjectFactory); + +export interface KeyMapListener { + +/** + * The full map plus the one key that changed — route `change` to the LK + * room(s) of that member. + */ + onKeyMapChange(keyMap: Array, change: FfiMediaKey): void; +} + + +export class KeyMapListenerImpl extends UniffiAbstractObject implements KeyMapListener { + + readonly [uniffiTypeNameSymbol] = "KeyMapListenerImpl"; + readonly [destructorGuardSymbol]: UniffiGcObject; + readonly [pointerLiteralSymbol]: UniffiHandle; + // No primary constructor declared for this class. +private constructor(pointer: UniffiHandle) { + super(); + this[pointerLiteralSymbol] = pointer; + this[destructorGuardSymbol] = uniffiTypeKeyMapListenerImplObjectFactory.bless(pointer); +} + + + + +/** + * The full map plus the one key that changed — route `change` to the LK + * room(s) of that member. + */ + onKeyMapChange(keyMap: Array, change: FfiMediaKey): void {uniffiCaller.rustCall( + /*caller:*/ (callStatus) => { nativeModule().ubrn_uniffi_matrix_rtc_fn_method_keymaplistener_on_key_map_change( + uniffiTypeKeyMapListenerImplObjectFactory.clonePointer(this), + FfiConverterSequenceTypeFfiMediaKey.lower(keyMap, nativeModule().rustbuffer_alloc), + FfiConverterTypeFfiMediaKey.lower(change, nativeModule().rustbuffer_alloc), + callStatus); + }, + /*liftString:*/ FfiConverterString.lift.bind(FfiConverterString), + ); + } + + + uniffiDestroy(): void { + const ptr = (this as any)[destructorGuardSymbol]; + if (ptr !== undefined) { + const pointer = uniffiTypeKeyMapListenerImplObjectFactory.pointer(this); + uniffiTypeKeyMapListenerImplObjectFactory.freePointer(pointer); + uniffiTypeKeyMapListenerImplObjectFactory.unbless(ptr); + delete (this as any)[destructorGuardSymbol]; + } + } + + static instanceOf(obj_: any): obj_ is KeyMapListenerImpl { + return uniffiTypeKeyMapListenerImplObjectFactory.isConcreteType(obj_); + } + + +} + +const uniffiTypeKeyMapListenerImplObjectFactory: UniffiObjectFactory = (() => { + + /// + const registry = typeof FinalizationRegistry !== 'undefined' ? new FinalizationRegistry((heldValue: UniffiHandle) => { + uniffiTypeKeyMapListenerImplObjectFactory.freePointer(heldValue); + }) : null; + + return { + create(pointer: UniffiHandle): KeyMapListener { + const instance = Object.create(KeyMapListenerImpl.prototype); + instance[pointerLiteralSymbol] = pointer; + instance[destructorGuardSymbol] = this.bless(pointer); + instance[uniffiTypeNameSymbol] = "KeyMapListenerImpl"; + return instance; + }, + + + bless(p: UniffiHandle): UniffiGcObject { + const ptr = { + p, // make sure this object doesn't get optimized away. + markDestroyed: () => undefined, + }; + if (registry) { + registry.register(ptr, p, ptr); + } + return ptr; + }, + + unbless(ptr_: UniffiGcObject) { + if (registry) { + registry.unregister(ptr_); + } + }, + + pointer(obj_: KeyMapListener): UniffiHandle { + if ((obj_ as any)[destructorGuardSymbol] === undefined) { + throw new UniffiInternalError.UnexpectedNullPointer(); + } + return (obj_ as any)[pointerLiteralSymbol]; + }, + + clonePointer(obj_: KeyMapListener): UniffiHandle { + const pointer = this.pointer(obj_); + return uniffiCaller.rustCall( + /*caller:*/ (callStatus) => nativeModule().ubrn_uniffi_matrix_rtc_fn_clone_keymaplistener(pointer, callStatus), + /*liftString:*/ FfiConverterString.lift + ); + }, + + freePointer(pointer: UniffiHandle): void { + uniffiCaller.rustCall( + /*caller:*/ (callStatus) => nativeModule().ubrn_uniffi_matrix_rtc_fn_free_keymaplistener(pointer, callStatus), + /*liftString:*/ FfiConverterString.lift + ); + }, + + isConcreteType(obj_: any): obj_ is KeyMapListener { + return obj_[destructorGuardSymbol] && obj_[uniffiTypeNameSymbol] === "KeyMapListenerImpl"; + }, +}})(); +const FfiConverterTypeKeyMapListener = new FfiConverterObjectWithCallbacks(uniffiTypeKeyMapListenerImplObjectFactory); + +// Add a vtable for the callbacks that go in KeyMapListener. + +// Put the implementation in a struct so we don't pollute the top-level namespace +const uniffiCallbackInterfaceKeyMapListener: { vtable: any; register: () => void; } = { + // Create the VTable using a series of closures. + // ts automatically converts these into C callback functions. + vtable: { + on_key_map_change: ( + uniffiHandle: bigint, + keyMap: Uint8Array, + change: Uint8Array,) => { + const uniffiMakeCall = + () + : void => { + const jsCallback = FfiConverterTypeKeyMapListener.lift(uniffiHandle); + return jsCallback.onKeyMapChange( + FfiConverterSequenceTypeFfiMediaKey.lift(keyMap), + FfiConverterTypeFfiMediaKey.lift(change) + ) + }; + const uniffiResult = UniffiResult.ready(); + const uniffiHandleSuccess = (obj: any) => {}; + const uniffiHandleError = (code: number, errBuf: UniffiByteArray) => { + UniffiResult.writeError(uniffiResult, code, errBuf); + }; + uniffiTraitInterfaceCall( + /*makeCall:*/ uniffiMakeCall, + /*handleSuccess:*/ uniffiHandleSuccess, + /*handleError:*/ uniffiHandleError, + /*lowerString:*/ FfiConverterString.lower.bind(FfiConverterString), + /*alloc:*/ nativeModule().rustbuffer_alloc, + ) + return uniffiResult; + }, + uniffi_free: (uniffiHandle: UniffiHandle): void => { + // this will throw a stale handle error if the handle isn't found. + FfiConverterTypeKeyMapListener.drop(uniffiHandle); + }, + uniffi_clone: (uniffiHandle: UniffiHandle): UniffiHandle => { + return FfiConverterTypeKeyMapListener.clone(uniffiHandle); + } + }, + register: () => {nativeModule().ubrn_uniffi_matrix_rtc_fn_init_callback_vtable_keymaplistener( + uniffiCallbackInterfaceKeyMapListener.vtable + ); + }, +}; + +export interface KeyRejectedListener { + +/** + * An inbound media key was discarded: `member_id` names whose, `reason` + * says why. + * + * **Secondary** to `FfiMembership::media_key.rejection` and + * `FfiImpairment::MediaKeyRejected`, which a UI attaching late still + * finds; this is for logging and telemetry. + */ + onKeyRejected(memberId: string, reason: FfiKeyRejection): void; +} + + +export class KeyRejectedListenerImpl extends UniffiAbstractObject implements KeyRejectedListener { + + readonly [uniffiTypeNameSymbol] = "KeyRejectedListenerImpl"; + readonly [destructorGuardSymbol]: UniffiGcObject; + readonly [pointerLiteralSymbol]: UniffiHandle; + // No primary constructor declared for this class. +private constructor(pointer: UniffiHandle) { + super(); + this[pointerLiteralSymbol] = pointer; + this[destructorGuardSymbol] = uniffiTypeKeyRejectedListenerImplObjectFactory.bless(pointer); +} + + + + +/** + * An inbound media key was discarded: `member_id` names whose, `reason` + * says why. + * + * **Secondary** to `FfiMembership::media_key.rejection` and + * `FfiImpairment::MediaKeyRejected`, which a UI attaching late still + * finds; this is for logging and telemetry. + */ + onKeyRejected(memberId: string, reason: FfiKeyRejection): void {uniffiCaller.rustCall( + /*caller:*/ (callStatus) => { nativeModule().ubrn_uniffi_matrix_rtc_fn_method_keyrejectedlistener_on_key_rejected( + uniffiTypeKeyRejectedListenerImplObjectFactory.clonePointer(this), + FfiConverterString.lower(memberId, nativeModule().rustbuffer_alloc), + FfiConverterTypeFfiKeyRejection.lower(reason, nativeModule().rustbuffer_alloc), + callStatus); + }, + /*liftString:*/ FfiConverterString.lift.bind(FfiConverterString), + ); + } + + + uniffiDestroy(): void { + const ptr = (this as any)[destructorGuardSymbol]; + if (ptr !== undefined) { + const pointer = uniffiTypeKeyRejectedListenerImplObjectFactory.pointer(this); + uniffiTypeKeyRejectedListenerImplObjectFactory.freePointer(pointer); + uniffiTypeKeyRejectedListenerImplObjectFactory.unbless(ptr); + delete (this as any)[destructorGuardSymbol]; + } + } + + static instanceOf(obj_: any): obj_ is KeyRejectedListenerImpl { + return uniffiTypeKeyRejectedListenerImplObjectFactory.isConcreteType(obj_); + } + + +} + +const uniffiTypeKeyRejectedListenerImplObjectFactory: UniffiObjectFactory = (() => { + + /// + const registry = typeof FinalizationRegistry !== 'undefined' ? new FinalizationRegistry((heldValue: UniffiHandle) => { + uniffiTypeKeyRejectedListenerImplObjectFactory.freePointer(heldValue); + }) : null; + + return { + create(pointer: UniffiHandle): KeyRejectedListener { + const instance = Object.create(KeyRejectedListenerImpl.prototype); + instance[pointerLiteralSymbol] = pointer; + instance[destructorGuardSymbol] = this.bless(pointer); + instance[uniffiTypeNameSymbol] = "KeyRejectedListenerImpl"; + return instance; + }, + + + bless(p: UniffiHandle): UniffiGcObject { + const ptr = { + p, // make sure this object doesn't get optimized away. + markDestroyed: () => undefined, + }; + if (registry) { + registry.register(ptr, p, ptr); + } + return ptr; + }, + + unbless(ptr_: UniffiGcObject) { + if (registry) { + registry.unregister(ptr_); + } + }, + + pointer(obj_: KeyRejectedListener): UniffiHandle { + if ((obj_ as any)[destructorGuardSymbol] === undefined) { + throw new UniffiInternalError.UnexpectedNullPointer(); + } + return (obj_ as any)[pointerLiteralSymbol]; + }, + + clonePointer(obj_: KeyRejectedListener): UniffiHandle { + const pointer = this.pointer(obj_); + return uniffiCaller.rustCall( + /*caller:*/ (callStatus) => nativeModule().ubrn_uniffi_matrix_rtc_fn_clone_keyrejectedlistener(pointer, callStatus), + /*liftString:*/ FfiConverterString.lift + ); + }, + + freePointer(pointer: UniffiHandle): void { + uniffiCaller.rustCall( + /*caller:*/ (callStatus) => nativeModule().ubrn_uniffi_matrix_rtc_fn_free_keyrejectedlistener(pointer, callStatus), + /*liftString:*/ FfiConverterString.lift + ); + }, + + isConcreteType(obj_: any): obj_ is KeyRejectedListener { + return obj_[destructorGuardSymbol] && obj_[uniffiTypeNameSymbol] === "KeyRejectedListenerImpl"; + }, +}})(); +const FfiConverterTypeKeyRejectedListener = new FfiConverterObjectWithCallbacks(uniffiTypeKeyRejectedListenerImplObjectFactory); + +// Add a vtable for the callbacks that go in KeyRejectedListener. + +// Put the implementation in a struct so we don't pollute the top-level namespace +const uniffiCallbackInterfaceKeyRejectedListener: { vtable: any; register: () => void; } = { + // Create the VTable using a series of closures. + // ts automatically converts these into C callback functions. + vtable: { + on_key_rejected: ( + uniffiHandle: bigint, + memberId: Uint8Array, + reason: Uint8Array,) => { + const uniffiMakeCall = + () + : void => { + const jsCallback = FfiConverterTypeKeyRejectedListener.lift(uniffiHandle); + return jsCallback.onKeyRejected( + FfiConverterString.lift(memberId), + FfiConverterTypeFfiKeyRejection.lift(reason) + ) + }; + const uniffiResult = UniffiResult.ready(); + const uniffiHandleSuccess = (obj: any) => {}; + const uniffiHandleError = (code: number, errBuf: UniffiByteArray) => { + UniffiResult.writeError(uniffiResult, code, errBuf); + }; + uniffiTraitInterfaceCall( + /*makeCall:*/ uniffiMakeCall, + /*handleSuccess:*/ uniffiHandleSuccess, + /*handleError:*/ uniffiHandleError, + /*lowerString:*/ FfiConverterString.lower.bind(FfiConverterString), + /*alloc:*/ nativeModule().rustbuffer_alloc, + ) + return uniffiResult; + }, + uniffi_free: (uniffiHandle: UniffiHandle): void => { + // this will throw a stale handle error if the handle isn't found. + FfiConverterTypeKeyRejectedListener.drop(uniffiHandle); + }, + uniffi_clone: (uniffiHandle: UniffiHandle): UniffiHandle => { + return FfiConverterTypeKeyRejectedListener.clone(uniffiHandle); + } + }, + register: () => {nativeModule().ubrn_uniffi_matrix_rtc_fn_init_callback_vtable_keyrejectedlistener( + uniffiCallbackInterfaceKeyRejectedListener.vtable + ); + }, +}; + +export interface MembershipsListener { + +/** + * One tile per membership; use the connections output to acquire each + * tile's media (`membership.connections` -> LK room, + * `membership.transport_identity` -> participant). + */ + onMembershipsChange(memberships: Array): void; +} + + +export class MembershipsListenerImpl extends UniffiAbstractObject implements MembershipsListener { + + readonly [uniffiTypeNameSymbol] = "MembershipsListenerImpl"; + readonly [destructorGuardSymbol]: UniffiGcObject; + readonly [pointerLiteralSymbol]: UniffiHandle; + // No primary constructor declared for this class. +private constructor(pointer: UniffiHandle) { + super(); + this[pointerLiteralSymbol] = pointer; + this[destructorGuardSymbol] = uniffiTypeMembershipsListenerImplObjectFactory.bless(pointer); +} + + + + +/** + * One tile per membership; use the connections output to acquire each + * tile's media (`membership.connections` -> LK room, + * `membership.transport_identity` -> participant). + */ + onMembershipsChange(memberships: Array): void {uniffiCaller.rustCall( + /*caller:*/ (callStatus) => { nativeModule().ubrn_uniffi_matrix_rtc_fn_method_membershipslistener_on_memberships_change( + uniffiTypeMembershipsListenerImplObjectFactory.clonePointer(this), + FfiConverterSequenceTypeFfiMembership.lower(memberships, nativeModule().rustbuffer_alloc), + callStatus); + }, + /*liftString:*/ FfiConverterString.lift.bind(FfiConverterString), + ); + } + + + uniffiDestroy(): void { + const ptr = (this as any)[destructorGuardSymbol]; + if (ptr !== undefined) { + const pointer = uniffiTypeMembershipsListenerImplObjectFactory.pointer(this); + uniffiTypeMembershipsListenerImplObjectFactory.freePointer(pointer); + uniffiTypeMembershipsListenerImplObjectFactory.unbless(ptr); + delete (this as any)[destructorGuardSymbol]; + } + } + + static instanceOf(obj_: any): obj_ is MembershipsListenerImpl { + return uniffiTypeMembershipsListenerImplObjectFactory.isConcreteType(obj_); + } + + +} + +const uniffiTypeMembershipsListenerImplObjectFactory: UniffiObjectFactory = (() => { + + /// + const registry = typeof FinalizationRegistry !== 'undefined' ? new FinalizationRegistry((heldValue: UniffiHandle) => { + uniffiTypeMembershipsListenerImplObjectFactory.freePointer(heldValue); + }) : null; + + return { + create(pointer: UniffiHandle): MembershipsListener { + const instance = Object.create(MembershipsListenerImpl.prototype); + instance[pointerLiteralSymbol] = pointer; + instance[destructorGuardSymbol] = this.bless(pointer); + instance[uniffiTypeNameSymbol] = "MembershipsListenerImpl"; + return instance; + }, + + + bless(p: UniffiHandle): UniffiGcObject { + const ptr = { + p, // make sure this object doesn't get optimized away. + markDestroyed: () => undefined, + }; + if (registry) { + registry.register(ptr, p, ptr); + } + return ptr; + }, + + unbless(ptr_: UniffiGcObject) { + if (registry) { + registry.unregister(ptr_); + } + }, + + pointer(obj_: MembershipsListener): UniffiHandle { + if ((obj_ as any)[destructorGuardSymbol] === undefined) { + throw new UniffiInternalError.UnexpectedNullPointer(); + } + return (obj_ as any)[pointerLiteralSymbol]; + }, + + clonePointer(obj_: MembershipsListener): UniffiHandle { + const pointer = this.pointer(obj_); + return uniffiCaller.rustCall( + /*caller:*/ (callStatus) => nativeModule().ubrn_uniffi_matrix_rtc_fn_clone_membershipslistener(pointer, callStatus), + /*liftString:*/ FfiConverterString.lift + ); + }, + + freePointer(pointer: UniffiHandle): void { + uniffiCaller.rustCall( + /*caller:*/ (callStatus) => nativeModule().ubrn_uniffi_matrix_rtc_fn_free_membershipslistener(pointer, callStatus), + /*liftString:*/ FfiConverterString.lift + ); + }, + + isConcreteType(obj_: any): obj_ is MembershipsListener { + return obj_[destructorGuardSymbol] && obj_[uniffiTypeNameSymbol] === "MembershipsListenerImpl"; + }, +}})(); +const FfiConverterTypeMembershipsListener = new FfiConverterObjectWithCallbacks(uniffiTypeMembershipsListenerImplObjectFactory); + +// Add a vtable for the callbacks that go in MembershipsListener. + +// Put the implementation in a struct so we don't pollute the top-level namespace +const uniffiCallbackInterfaceMembershipsListener: { vtable: any; register: () => void; } = { + // Create the VTable using a series of closures. + // ts automatically converts these into C callback functions. + vtable: { + on_memberships_change: ( + uniffiHandle: bigint, + memberships: Uint8Array,) => { + const uniffiMakeCall = + () + : void => { + const jsCallback = FfiConverterTypeMembershipsListener.lift(uniffiHandle); + return jsCallback.onMembershipsChange( + FfiConverterSequenceTypeFfiMembership.lift(memberships) + ) + }; + const uniffiResult = UniffiResult.ready(); + const uniffiHandleSuccess = (obj: any) => {}; + const uniffiHandleError = (code: number, errBuf: UniffiByteArray) => { + UniffiResult.writeError(uniffiResult, code, errBuf); + }; + uniffiTraitInterfaceCall( + /*makeCall:*/ uniffiMakeCall, + /*handleSuccess:*/ uniffiHandleSuccess, + /*handleError:*/ uniffiHandleError, + /*lowerString:*/ FfiConverterString.lower.bind(FfiConverterString), + /*alloc:*/ nativeModule().rustbuffer_alloc, + ) + return uniffiResult; + }, + uniffi_free: (uniffiHandle: UniffiHandle): void => { + // this will throw a stale handle error if the handle isn't found. + FfiConverterTypeMembershipsListener.drop(uniffiHandle); + }, + uniffi_clone: (uniffiHandle: UniffiHandle): UniffiHandle => { + return FfiConverterTypeMembershipsListener.clone(uniffiHandle); + } + }, + register: () => {nativeModule().ubrn_uniffi_matrix_rtc_fn_init_callback_vtable_membershipslistener( + uniffiCallbackInterfaceMembershipsListener.vtable + ); + }, +}; + +export interface StatusListener { + + onStatusChange(status: FfiStatus): void; +} + + +export class StatusListenerImpl extends UniffiAbstractObject implements StatusListener { + + readonly [uniffiTypeNameSymbol] = "StatusListenerImpl"; + readonly [destructorGuardSymbol]: UniffiGcObject; + readonly [pointerLiteralSymbol]: UniffiHandle; + // No primary constructor declared for this class. +private constructor(pointer: UniffiHandle) { + super(); + this[pointerLiteralSymbol] = pointer; + this[destructorGuardSymbol] = uniffiTypeStatusListenerImplObjectFactory.bless(pointer); +} + + + + + onStatusChange(status: FfiStatus): void {uniffiCaller.rustCall( + /*caller:*/ (callStatus) => { nativeModule().ubrn_uniffi_matrix_rtc_fn_method_statuslistener_on_status_change( + uniffiTypeStatusListenerImplObjectFactory.clonePointer(this), + FfiConverterTypeFfiStatus.lower(status, nativeModule().rustbuffer_alloc), + callStatus); + }, + /*liftString:*/ FfiConverterString.lift.bind(FfiConverterString), + ); + } + + + uniffiDestroy(): void { + const ptr = (this as any)[destructorGuardSymbol]; + if (ptr !== undefined) { + const pointer = uniffiTypeStatusListenerImplObjectFactory.pointer(this); + uniffiTypeStatusListenerImplObjectFactory.freePointer(pointer); + uniffiTypeStatusListenerImplObjectFactory.unbless(ptr); + delete (this as any)[destructorGuardSymbol]; + } + } + + static instanceOf(obj_: any): obj_ is StatusListenerImpl { + return uniffiTypeStatusListenerImplObjectFactory.isConcreteType(obj_); + } + + +} + +const uniffiTypeStatusListenerImplObjectFactory: UniffiObjectFactory = (() => { + + /// + const registry = typeof FinalizationRegistry !== 'undefined' ? new FinalizationRegistry((heldValue: UniffiHandle) => { + uniffiTypeStatusListenerImplObjectFactory.freePointer(heldValue); + }) : null; + + return { + create(pointer: UniffiHandle): StatusListener { + const instance = Object.create(StatusListenerImpl.prototype); + instance[pointerLiteralSymbol] = pointer; + instance[destructorGuardSymbol] = this.bless(pointer); + instance[uniffiTypeNameSymbol] = "StatusListenerImpl"; + return instance; + }, + + + bless(p: UniffiHandle): UniffiGcObject { + const ptr = { + p, // make sure this object doesn't get optimized away. + markDestroyed: () => undefined, + }; + if (registry) { + registry.register(ptr, p, ptr); + } + return ptr; + }, + + unbless(ptr_: UniffiGcObject) { + if (registry) { + registry.unregister(ptr_); + } + }, + + pointer(obj_: StatusListener): UniffiHandle { + if ((obj_ as any)[destructorGuardSymbol] === undefined) { + throw new UniffiInternalError.UnexpectedNullPointer(); + } + return (obj_ as any)[pointerLiteralSymbol]; + }, + + clonePointer(obj_: StatusListener): UniffiHandle { + const pointer = this.pointer(obj_); + return uniffiCaller.rustCall( + /*caller:*/ (callStatus) => nativeModule().ubrn_uniffi_matrix_rtc_fn_clone_statuslistener(pointer, callStatus), + /*liftString:*/ FfiConverterString.lift + ); + }, + + freePointer(pointer: UniffiHandle): void { + uniffiCaller.rustCall( + /*caller:*/ (callStatus) => nativeModule().ubrn_uniffi_matrix_rtc_fn_free_statuslistener(pointer, callStatus), + /*liftString:*/ FfiConverterString.lift + ); + }, + + isConcreteType(obj_: any): obj_ is StatusListener { + return obj_[destructorGuardSymbol] && obj_[uniffiTypeNameSymbol] === "StatusListenerImpl"; + }, +}})(); +const FfiConverterTypeStatusListener = new FfiConverterObjectWithCallbacks(uniffiTypeStatusListenerImplObjectFactory); + +// Add a vtable for the callbacks that go in StatusListener. + +// Put the implementation in a struct so we don't pollute the top-level namespace +const uniffiCallbackInterfaceStatusListener: { vtable: any; register: () => void; } = { + // Create the VTable using a series of closures. + // ts automatically converts these into C callback functions. + vtable: { + on_status_change: ( + uniffiHandle: bigint, + status: Uint8Array,) => { + const uniffiMakeCall = + () + : void => { + const jsCallback = FfiConverterTypeStatusListener.lift(uniffiHandle); + return jsCallback.onStatusChange( + FfiConverterTypeFfiStatus.lift(status) + ) + }; + const uniffiResult = UniffiResult.ready(); + const uniffiHandleSuccess = (obj: any) => {}; + const uniffiHandleError = (code: number, errBuf: UniffiByteArray) => { + UniffiResult.writeError(uniffiResult, code, errBuf); + }; + uniffiTraitInterfaceCall( + /*makeCall:*/ uniffiMakeCall, + /*handleSuccess:*/ uniffiHandleSuccess, + /*handleError:*/ uniffiHandleError, + /*lowerString:*/ FfiConverterString.lower.bind(FfiConverterString), + /*alloc:*/ nativeModule().rustbuffer_alloc, + ) + return uniffiResult; + }, + uniffi_free: (uniffiHandle: UniffiHandle): void => { + // this will throw a stale handle error if the handle isn't found. + FfiConverterTypeStatusListener.drop(uniffiHandle); + }, + uniffi_clone: (uniffiHandle: UniffiHandle): UniffiHandle => { + return FfiConverterTypeStatusListener.clone(uniffiHandle); + } + }, + register: () => {nativeModule().ubrn_uniffi_matrix_rtc_fn_init_callback_vtable_statuslistener( + uniffiCallbackInterfaceStatusListener.vtable + ); + }, +}; + +/** + * FFI wrapper around [`ParticipationManager`]. + */ +export interface FfiParticipationManagerLike { + + closeSlot(asyncOpts_?: { signal: AbortSignal }) /*throws*/: Promise; +/** + * Wanted connections the host cannot currently use, with the members + * whose media is affected. Empty is the healthy case. + */ + connectionProblems(): Array; + connections(): Array; +/** + * Diagnostics JSON: an unversioned dump for bug reports, **not** a UI + * contract. Everything a UI needs is typed on `status()`, + * `session()`, `memberships()` and `connection_problems()`. + */ + debugSnapshot(): string; +/** + * Whether the driver currently reports the homeserver reachable. Inside a + * participation the same fact is `FfiImpairment::HomeserverUnreachable` + * in the status; this covers the lobby and the post-call screen. + */ + isHomeserverConnected(): boolean; + join(intent: FfiTransportIntent, params: FfiJoinParams, asyncOpts_?: { signal: AbortSignal }) /*throws*/: Promise; + keyMap(): Array; +/** + * `code` defaults to MSC4143's plain `leave`. + */ + leave(code: string | undefined, reason: string | undefined, asyncOpts_?: { signal: AbortSignal }) /*throws*/: Promise; +/** + * The session's joined projection plus left members still holding our + * keys (see [`FfiMembershipState`]). + */ + memberships(): Array; + openSlot(applicationType: string, encrypted: boolean, asyncOpts_?: { signal: AbortSignal }) /*throws*/: Promise; +/** + * Open this manager's slot (`m.per_member` encryption when `encrypted`). + * Our member id for this participation; `None` while not joined. + * + * Every self-referential check needs it — am I in the roster + * (`session().excluded_candidates`), which LiveKit participant is me + * (`own_membership().transport_identity`). Matching on + * `(user_id, device_id)` is not a substitute: one device may hold + * several RTC members, and a rejoin mints a fresh id. + */ + ownMemberId(): string | undefined; +/** + * Our own entry in `memberships()`, when the session projects it. + */ + ownMembership(): FfiMembership | undefined; +/** + * Our LiveKit participant identity, known from the moment `join()` + * starts (before our membership echo). `None` while not joined. + */ + ownTransportIdentity(): string | undefined; +/** + * The live session snapshot (slot open?, encrypted?, members, start + * time) — the same record `compute_sessions_from_events` returns. + */ + session(): FfiSessionSnapshot; + setConnectionsListener(listener: ConnectionsListener): void; + setKeyMapListener(listener: KeyMapListener): void; + setKeyRejectedListener(listener: KeyRejectedListener): void; + setMembershipsListener(listener: MembershipsListener): void; + setStatusListener(listener: StatusListener): void; + status(): FfiStatus; +/** + * Change `application["m.call.intent"]` (e.g. `"audio"` / `"video"`) + * while joined: the membership is re-published with it. `None` removes + * the intent. Rejects with `NotJoined` outside a participation. + */ + updateApplication(intent: string | undefined, asyncOpts_?: { signal: AbortSignal }) /*throws*/: Promise; +} +/** + * @deprecated Use `FfiParticipationManagerLike` instead. + */ +export type FfiParticipationManagerInterface = FfiParticipationManagerLike; + + +/** + * FFI wrapper around [`ParticipationManager`]. + */ +export class FfiParticipationManager extends UniffiAbstractObject implements FfiParticipationManagerLike { + + readonly [uniffiTypeNameSymbol] = "FfiParticipationManager"; + readonly [destructorGuardSymbol]: UniffiGcObject; + readonly [pointerLiteralSymbol]: UniffiHandle; +/** + * One manager per `(room, slot)`; `user_id`/`device_id` are who we + * publish as. Any number of managers may share one driver. + */ + constructor(roomId: string, slotId: string, userId: string, deviceId: string, driver: FfiMatrixDriverLike, config: FfiParticipationConfig) { + super(); + const pointer = + uniffiCaller.rustCall( + /*caller:*/ (callStatus) => { + return nativeModule().ubrn_uniffi_matrix_rtc_fn_constructor_ffiparticipationmanager_new( + FfiConverterString.lower(roomId, nativeModule().rustbuffer_alloc), + FfiConverterString.lower(slotId, nativeModule().rustbuffer_alloc), + FfiConverterString.lower(userId, nativeModule().rustbuffer_alloc), + FfiConverterString.lower(deviceId, nativeModule().rustbuffer_alloc), + FfiConverterTypeFfiMatrixDriver.lower(driver, nativeModule().rustbuffer_alloc), + FfiConverterTypeFfiParticipationConfig.lower(config, nativeModule().rustbuffer_alloc), + callStatus); + }, + /*liftString:*/ FfiConverterString.lift.bind(FfiConverterString), + ); + this[pointerLiteralSymbol] = pointer; + this[destructorGuardSymbol] = uniffiTypeFfiParticipationManagerObjectFactory.bless(pointer); + } + + + + + async closeSlot(asyncOpts_?: { signal: AbortSignal }): Promise /*throws*/ { + return await uniffiRustCallAsync( + /*rustCaller:*/ uniffiCaller, + /*rustFutureFunc:*/ () => { + return nativeModule().ubrn_uniffi_matrix_rtc_fn_method_ffiparticipationmanager_close_slot( + uniffiTypeFfiParticipationManagerObjectFactory.clonePointer(this) + ); + }, + /*pollFunc:*/ nativeModule().ubrn_ffi_matrix_rtc_rust_future_poll_void, + /*cancelFunc:*/ nativeModule().ubrn_ffi_matrix_rtc_rust_future_cancel_void, + /*completeFunc:*/ nativeModule().ubrn_ffi_matrix_rtc_rust_future_complete_void, + /*freeFunc:*/ nativeModule().ubrn_ffi_matrix_rtc_rust_future_free_void, + /*liftFunc:*/ (_v) => {}, + /*liftString:*/ FfiConverterString.lift.bind(FfiConverterString), + /*asyncOpts:*/ asyncOpts_, + /*errorHandler:*/ FfiConverterTypeRtcError.lift.bind(FfiConverterTypeRtcError) + ); + } + +/** + * Wanted connections the host cannot currently use, with the members + * whose media is affected. Empty is the healthy case. + */ + connectionProblems(): Array { + const __rb: Uint8Array = uniffiCaller.rustCall( + /*caller:*/ (callStatus) => { + return nativeModule().ubrn_uniffi_matrix_rtc_fn_method_ffiparticipationmanager_connection_problems( + uniffiTypeFfiParticipationManagerObjectFactory.clonePointer(this), + callStatus); + }, + /*liftString:*/ FfiConverterString.lift.bind(FfiConverterString), + ); + try { + return FfiConverterSequenceTypeFfiConnectionProblem.lift(__rb); + } finally { + nativeModule().rustbuffer_free(__rb); + } + } + + connections(): Array { + const __rb: Uint8Array = uniffiCaller.rustCall( + /*caller:*/ (callStatus) => { + return nativeModule().ubrn_uniffi_matrix_rtc_fn_method_ffiparticipationmanager_connections( + uniffiTypeFfiParticipationManagerObjectFactory.clonePointer(this), + callStatus); + }, + /*liftString:*/ FfiConverterString.lift.bind(FfiConverterString), + ); + try { + return FfiConverterSequenceTypeFfiConnectionWithMembers.lift(__rb); + } finally { + nativeModule().rustbuffer_free(__rb); + } + } + +/** + * Diagnostics JSON: an unversioned dump for bug reports, **not** a UI + * contract. Everything a UI needs is typed on `status()`, + * `session()`, `memberships()` and `connection_problems()`. + */ + debugSnapshot(): string { + const __rb: Uint8Array = uniffiCaller.rustCall( + /*caller:*/ (callStatus) => { + return nativeModule().ubrn_uniffi_matrix_rtc_fn_method_ffiparticipationmanager_debug_snapshot( + uniffiTypeFfiParticipationManagerObjectFactory.clonePointer(this), + callStatus); + }, + /*liftString:*/ FfiConverterString.lift.bind(FfiConverterString), + ); + try { + return FfiConverterString.lift(__rb); + } finally { + nativeModule().rustbuffer_free(__rb); + } + } + +/** + * Whether the driver currently reports the homeserver reachable. Inside a + * participation the same fact is `FfiImpairment::HomeserverUnreachable` + * in the status; this covers the lobby and the post-call screen. + */ + isHomeserverConnected(): boolean { + return FfiConverterBool.lift(uniffiCaller.rustCall( + /*caller:*/ (callStatus) => { + return nativeModule().ubrn_uniffi_matrix_rtc_fn_method_ffiparticipationmanager_is_homeserver_connected( + uniffiTypeFfiParticipationManagerObjectFactory.clonePointer(this), + callStatus); + }, + /*liftString:*/ FfiConverterString.lift.bind(FfiConverterString), + )); + } + + async join(intent: FfiTransportIntent, params: FfiJoinParams, asyncOpts_?: { signal: AbortSignal }): Promise /*throws*/ { + return await uniffiRustCallAsync( + /*rustCaller:*/ uniffiCaller, + /*rustFutureFunc:*/ () => { + return nativeModule().ubrn_uniffi_matrix_rtc_fn_method_ffiparticipationmanager_join( + uniffiTypeFfiParticipationManagerObjectFactory.clonePointer(this),FfiConverterTypeFfiTransportIntent.lower(intent, nativeModule().rustbuffer_alloc),FfiConverterTypeFfiJoinParams.lower(params, nativeModule().rustbuffer_alloc) + ); + }, + /*pollFunc:*/ nativeModule().ubrn_ffi_matrix_rtc_rust_future_poll_void, + /*cancelFunc:*/ nativeModule().ubrn_ffi_matrix_rtc_rust_future_cancel_void, + /*completeFunc:*/ nativeModule().ubrn_ffi_matrix_rtc_rust_future_complete_void, + /*freeFunc:*/ nativeModule().ubrn_ffi_matrix_rtc_rust_future_free_void, + /*liftFunc:*/ (_v) => {}, + /*liftString:*/ FfiConverterString.lift.bind(FfiConverterString), + /*asyncOpts:*/ asyncOpts_, + /*errorHandler:*/ FfiConverterTypeRtcError.lift.bind(FfiConverterTypeRtcError) + ); + } + + keyMap(): Array { + const __rb: Uint8Array = uniffiCaller.rustCall( + /*caller:*/ (callStatus) => { + return nativeModule().ubrn_uniffi_matrix_rtc_fn_method_ffiparticipationmanager_key_map( + uniffiTypeFfiParticipationManagerObjectFactory.clonePointer(this), + callStatus); + }, + /*liftString:*/ FfiConverterString.lift.bind(FfiConverterString), + ); + try { + return FfiConverterSequenceTypeFfiMediaKey.lift(__rb); + } finally { + nativeModule().rustbuffer_free(__rb); + } + } + +/** + * `code` defaults to MSC4143's plain `leave`. + */ + async leave(code: string | undefined, reason: string | undefined, asyncOpts_?: { signal: AbortSignal }): Promise /*throws*/ { + return await uniffiRustCallAsync( + /*rustCaller:*/ uniffiCaller, + /*rustFutureFunc:*/ () => { + return nativeModule().ubrn_uniffi_matrix_rtc_fn_method_ffiparticipationmanager_leave( + uniffiTypeFfiParticipationManagerObjectFactory.clonePointer(this),FfiConverterOptionalString.lower(code, nativeModule().rustbuffer_alloc),FfiConverterOptionalString.lower(reason, nativeModule().rustbuffer_alloc) + ); + }, + /*pollFunc:*/ nativeModule().ubrn_ffi_matrix_rtc_rust_future_poll_void, + /*cancelFunc:*/ nativeModule().ubrn_ffi_matrix_rtc_rust_future_cancel_void, + /*completeFunc:*/ nativeModule().ubrn_ffi_matrix_rtc_rust_future_complete_void, + /*freeFunc:*/ nativeModule().ubrn_ffi_matrix_rtc_rust_future_free_void, + /*liftFunc:*/ (_v) => {}, + /*liftString:*/ FfiConverterString.lift.bind(FfiConverterString), + /*asyncOpts:*/ asyncOpts_, + /*errorHandler:*/ FfiConverterTypeRtcError.lift.bind(FfiConverterTypeRtcError) + ); + } + +/** + * The session's joined projection plus left members still holding our + * keys (see [`FfiMembershipState`]). + */ + memberships(): Array { + const __rb: Uint8Array = uniffiCaller.rustCall( + /*caller:*/ (callStatus) => { + return nativeModule().ubrn_uniffi_matrix_rtc_fn_method_ffiparticipationmanager_memberships( + uniffiTypeFfiParticipationManagerObjectFactory.clonePointer(this), + callStatus); + }, + /*liftString:*/ FfiConverterString.lift.bind(FfiConverterString), + ); + try { + return FfiConverterSequenceTypeFfiMembership.lift(__rb); + } finally { + nativeModule().rustbuffer_free(__rb); + } + } + + async openSlot(applicationType: string, encrypted: boolean, asyncOpts_?: { signal: AbortSignal }): Promise /*throws*/ { + return await uniffiRustCallAsync( + /*rustCaller:*/ uniffiCaller, + /*rustFutureFunc:*/ () => { + return nativeModule().ubrn_uniffi_matrix_rtc_fn_method_ffiparticipationmanager_open_slot( + uniffiTypeFfiParticipationManagerObjectFactory.clonePointer(this),FfiConverterString.lower(applicationType, nativeModule().rustbuffer_alloc),FfiConverterBool.lower(encrypted, nativeModule().rustbuffer_alloc) + ); + }, + /*pollFunc:*/ nativeModule().ubrn_ffi_matrix_rtc_rust_future_poll_void, + /*cancelFunc:*/ nativeModule().ubrn_ffi_matrix_rtc_rust_future_cancel_void, + /*completeFunc:*/ nativeModule().ubrn_ffi_matrix_rtc_rust_future_complete_void, + /*freeFunc:*/ nativeModule().ubrn_ffi_matrix_rtc_rust_future_free_void, + /*liftFunc:*/ (_v) => {}, + /*liftString:*/ FfiConverterString.lift.bind(FfiConverterString), + /*asyncOpts:*/ asyncOpts_, + /*errorHandler:*/ FfiConverterTypeRtcError.lift.bind(FfiConverterTypeRtcError) + ); + } + +/** + * Open this manager's slot (`m.per_member` encryption when `encrypted`). + * Our member id for this participation; `None` while not joined. + * + * Every self-referential check needs it — am I in the roster + * (`session().excluded_candidates`), which LiveKit participant is me + * (`own_membership().transport_identity`). Matching on + * `(user_id, device_id)` is not a substitute: one device may hold + * several RTC members, and a rejoin mints a fresh id. + */ + ownMemberId(): string | undefined { + const __rb: Uint8Array = uniffiCaller.rustCall( + /*caller:*/ (callStatus) => { + return nativeModule().ubrn_uniffi_matrix_rtc_fn_method_ffiparticipationmanager_own_member_id( + uniffiTypeFfiParticipationManagerObjectFactory.clonePointer(this), + callStatus); + }, + /*liftString:*/ FfiConverterString.lift.bind(FfiConverterString), + ); + try { + return FfiConverterOptionalString.lift(__rb); + } finally { + nativeModule().rustbuffer_free(__rb); + } + } + +/** + * Our own entry in `memberships()`, when the session projects it. + */ + ownMembership(): FfiMembership | undefined { + const __rb: Uint8Array = uniffiCaller.rustCall( + /*caller:*/ (callStatus) => { + return nativeModule().ubrn_uniffi_matrix_rtc_fn_method_ffiparticipationmanager_own_membership( + uniffiTypeFfiParticipationManagerObjectFactory.clonePointer(this), + callStatus); + }, + /*liftString:*/ FfiConverterString.lift.bind(FfiConverterString), + ); + try { + return FfiConverterOptionalTypeFfiMembership.lift(__rb); + } finally { + nativeModule().rustbuffer_free(__rb); + } + } + +/** + * Our LiveKit participant identity, known from the moment `join()` + * starts (before our membership echo). `None` while not joined. + */ + ownTransportIdentity(): string | undefined { + const __rb: Uint8Array = uniffiCaller.rustCall( + /*caller:*/ (callStatus) => { + return nativeModule().ubrn_uniffi_matrix_rtc_fn_method_ffiparticipationmanager_own_transport_identity( + uniffiTypeFfiParticipationManagerObjectFactory.clonePointer(this), + callStatus); + }, + /*liftString:*/ FfiConverterString.lift.bind(FfiConverterString), + ); + try { + return FfiConverterOptionalString.lift(__rb); + } finally { + nativeModule().rustbuffer_free(__rb); + } + } + +/** + * The live session snapshot (slot open?, encrypted?, members, start + * time) — the same record `compute_sessions_from_events` returns. + */ + session(): FfiSessionSnapshot { + const __rb: Uint8Array = uniffiCaller.rustCall( + /*caller:*/ (callStatus) => { + return nativeModule().ubrn_uniffi_matrix_rtc_fn_method_ffiparticipationmanager_session( + uniffiTypeFfiParticipationManagerObjectFactory.clonePointer(this), + callStatus); + }, + /*liftString:*/ FfiConverterString.lift.bind(FfiConverterString), + ); + try { + return FfiConverterTypeFfiSessionSnapshot.lift(__rb); + } finally { + nativeModule().rustbuffer_free(__rb); + } + } + + setConnectionsListener(listener: ConnectionsListener): void {uniffiCaller.rustCall( + /*caller:*/ (callStatus) => { nativeModule().ubrn_uniffi_matrix_rtc_fn_method_ffiparticipationmanager_set_connections_listener( + uniffiTypeFfiParticipationManagerObjectFactory.clonePointer(this), + FfiConverterTypeConnectionsListener.lower(listener, nativeModule().rustbuffer_alloc), + callStatus); + }, + /*liftString:*/ FfiConverterString.lift.bind(FfiConverterString), + ); + } + + setKeyMapListener(listener: KeyMapListener): void {uniffiCaller.rustCall( + /*caller:*/ (callStatus) => { nativeModule().ubrn_uniffi_matrix_rtc_fn_method_ffiparticipationmanager_set_key_map_listener( + uniffiTypeFfiParticipationManagerObjectFactory.clonePointer(this), + FfiConverterTypeKeyMapListener.lower(listener, nativeModule().rustbuffer_alloc), + callStatus); + }, + /*liftString:*/ FfiConverterString.lift.bind(FfiConverterString), + ); + } + + setKeyRejectedListener(listener: KeyRejectedListener): void {uniffiCaller.rustCall( + /*caller:*/ (callStatus) => { nativeModule().ubrn_uniffi_matrix_rtc_fn_method_ffiparticipationmanager_set_key_rejected_listener( + uniffiTypeFfiParticipationManagerObjectFactory.clonePointer(this), + FfiConverterTypeKeyRejectedListener.lower(listener, nativeModule().rustbuffer_alloc), + callStatus); + }, + /*liftString:*/ FfiConverterString.lift.bind(FfiConverterString), + ); + } + + setMembershipsListener(listener: MembershipsListener): void {uniffiCaller.rustCall( + /*caller:*/ (callStatus) => { nativeModule().ubrn_uniffi_matrix_rtc_fn_method_ffiparticipationmanager_set_memberships_listener( + uniffiTypeFfiParticipationManagerObjectFactory.clonePointer(this), + FfiConverterTypeMembershipsListener.lower(listener, nativeModule().rustbuffer_alloc), + callStatus); + }, + /*liftString:*/ FfiConverterString.lift.bind(FfiConverterString), + ); + } + + setStatusListener(listener: StatusListener): void {uniffiCaller.rustCall( + /*caller:*/ (callStatus) => { nativeModule().ubrn_uniffi_matrix_rtc_fn_method_ffiparticipationmanager_set_status_listener( + uniffiTypeFfiParticipationManagerObjectFactory.clonePointer(this), + FfiConverterTypeStatusListener.lower(listener, nativeModule().rustbuffer_alloc), + callStatus); + }, + /*liftString:*/ FfiConverterString.lift.bind(FfiConverterString), + ); + } + + status(): FfiStatus { + const __rb: Uint8Array = uniffiCaller.rustCall( + /*caller:*/ (callStatus) => { + return nativeModule().ubrn_uniffi_matrix_rtc_fn_method_ffiparticipationmanager_status( + uniffiTypeFfiParticipationManagerObjectFactory.clonePointer(this), + callStatus); + }, + /*liftString:*/ FfiConverterString.lift.bind(FfiConverterString), + ); + try { + return FfiConverterTypeFfiStatus.lift(__rb); + } finally { + nativeModule().rustbuffer_free(__rb); + } + } + +/** + * Change `application["m.call.intent"]` (e.g. `"audio"` / `"video"`) + * while joined: the membership is re-published with it. `None` removes + * the intent. Rejects with `NotJoined` outside a participation. + */ + async updateApplication(intent: string | undefined, asyncOpts_?: { signal: AbortSignal }): Promise /*throws*/ { + return await uniffiRustCallAsync( + /*rustCaller:*/ uniffiCaller, + /*rustFutureFunc:*/ () => { + return nativeModule().ubrn_uniffi_matrix_rtc_fn_method_ffiparticipationmanager_update_application( + uniffiTypeFfiParticipationManagerObjectFactory.clonePointer(this),FfiConverterOptionalString.lower(intent, nativeModule().rustbuffer_alloc) + ); + }, + /*pollFunc:*/ nativeModule().ubrn_ffi_matrix_rtc_rust_future_poll_void, + /*cancelFunc:*/ nativeModule().ubrn_ffi_matrix_rtc_rust_future_cancel_void, + /*completeFunc:*/ nativeModule().ubrn_ffi_matrix_rtc_rust_future_complete_void, + /*freeFunc:*/ nativeModule().ubrn_ffi_matrix_rtc_rust_future_free_void, + /*liftFunc:*/ (_v) => {}, + /*liftString:*/ FfiConverterString.lift.bind(FfiConverterString), + /*asyncOpts:*/ asyncOpts_, + /*errorHandler:*/ FfiConverterTypeRtcError.lift.bind(FfiConverterTypeRtcError) + ); + } + + + uniffiDestroy(): void { + const ptr = (this as any)[destructorGuardSymbol]; + if (ptr !== undefined) { + const pointer = uniffiTypeFfiParticipationManagerObjectFactory.pointer(this); + uniffiTypeFfiParticipationManagerObjectFactory.freePointer(pointer); + uniffiTypeFfiParticipationManagerObjectFactory.unbless(ptr); + delete (this as any)[destructorGuardSymbol]; + } + } + + static instanceOf(obj_: any): obj_ is FfiParticipationManager { + return uniffiTypeFfiParticipationManagerObjectFactory.isConcreteType(obj_); + } + + +} + +const uniffiTypeFfiParticipationManagerObjectFactory: UniffiObjectFactory = (() => { + + /// + const registry = typeof FinalizationRegistry !== 'undefined' ? new FinalizationRegistry((heldValue: UniffiHandle) => { + uniffiTypeFfiParticipationManagerObjectFactory.freePointer(heldValue); + }) : null; + + return { + create(pointer: UniffiHandle): FfiParticipationManagerLike { + const instance = Object.create(FfiParticipationManager.prototype); + instance[pointerLiteralSymbol] = pointer; + instance[destructorGuardSymbol] = this.bless(pointer); + instance[uniffiTypeNameSymbol] = "FfiParticipationManager"; + return instance; + }, + + + bless(p: UniffiHandle): UniffiGcObject { + const ptr = { + p, // make sure this object doesn't get optimized away. + markDestroyed: () => undefined, + }; + if (registry) { + registry.register(ptr, p, ptr); + } + return ptr; + }, + + unbless(ptr_: UniffiGcObject) { + if (registry) { + registry.unregister(ptr_); + } + }, + + pointer(obj_: FfiParticipationManagerLike): UniffiHandle { + if ((obj_ as any)[destructorGuardSymbol] === undefined) { + throw new UniffiInternalError.UnexpectedNullPointer(); + } + return (obj_ as any)[pointerLiteralSymbol]; + }, + + clonePointer(obj_: FfiParticipationManagerLike): UniffiHandle { + const pointer = this.pointer(obj_); + return uniffiCaller.rustCall( + /*caller:*/ (callStatus) => nativeModule().ubrn_uniffi_matrix_rtc_fn_clone_ffiparticipationmanager(pointer, callStatus), + /*liftString:*/ FfiConverterString.lift + ); + }, + + freePointer(pointer: UniffiHandle): void { + uniffiCaller.rustCall( + /*caller:*/ (callStatus) => nativeModule().ubrn_uniffi_matrix_rtc_fn_free_ffiparticipationmanager(pointer, callStatus), + /*liftString:*/ FfiConverterString.lift + ); + }, + + isConcreteType(obj_: any): obj_ is FfiParticipationManagerLike { + return obj_[destructorGuardSymbol] && obj_[uniffiTypeNameSymbol] === "FfiParticipationManager"; + }, +}})(); +const FfiConverterTypeFfiParticipationManager = new FfiConverterObject(uniffiTypeFfiParticipationManagerObjectFactory); + +/** + * One end of a driver event stream: Rust-exported objects handed to the + * foreign driver through the `subscribe_*` methods. The host calls `emit` + * from its own event handlers (e.g. matrix-js-sdk listeners); `false` means + * the Rust side dropped the stream — unhook the handler (this plays the + * role of matrix-rust-sdk's `EventHandlerDropGuard`). + */ +export interface RoomEventSinkLike { + +/** + * Any room event — sticky or state; the session dispatches on type. + * `event_json` is the full event object (see `session::dispatch`), the + * *decrypted* one for encrypted events, with `origin` carrying the + * decryption metadata. Returns `false` once no consumer is left. + */ + emit(eventJson: string, origin: FfiEventOrigin): boolean; +} +/** + * @deprecated Use `RoomEventSinkLike` instead. + */ +export type RoomEventSinkInterface = RoomEventSinkLike; + + +/** + * One end of a driver event stream: Rust-exported objects handed to the + * foreign driver through the `subscribe_*` methods. The host calls `emit` + * from its own event handlers (e.g. matrix-js-sdk listeners); `false` means + * the Rust side dropped the stream — unhook the handler (this plays the + * role of matrix-rust-sdk's `EventHandlerDropGuard`). + */ +export class RoomEventSink extends UniffiAbstractObject implements RoomEventSinkLike { + + readonly [uniffiTypeNameSymbol] = "RoomEventSink"; + readonly [destructorGuardSymbol]: UniffiGcObject; + readonly [pointerLiteralSymbol]: UniffiHandle; + // No primary constructor declared for this class. +private constructor(pointer: UniffiHandle) { + super(); + this[pointerLiteralSymbol] = pointer; + this[destructorGuardSymbol] = uniffiTypeRoomEventSinkObjectFactory.bless(pointer); +} + + + + +/** + * Any room event — sticky or state; the session dispatches on type. + * `event_json` is the full event object (see `session::dispatch`), the + * *decrypted* one for encrypted events, with `origin` carrying the + * decryption metadata. Returns `false` once no consumer is left. + */ + emit(eventJson: string, origin: FfiEventOrigin): boolean { + return FfiConverterBool.lift(uniffiCaller.rustCall( + /*caller:*/ (callStatus) => { + return nativeModule().ubrn_uniffi_matrix_rtc_fn_method_roomeventsink_emit( + uniffiTypeRoomEventSinkObjectFactory.clonePointer(this), + FfiConverterString.lower(eventJson, nativeModule().rustbuffer_alloc), + FfiConverterTypeFfiEventOrigin.lower(origin, nativeModule().rustbuffer_alloc), + callStatus); + }, + /*liftString:*/ FfiConverterString.lift.bind(FfiConverterString), + )); + } + + + uniffiDestroy(): void { + const ptr = (this as any)[destructorGuardSymbol]; + if (ptr !== undefined) { + const pointer = uniffiTypeRoomEventSinkObjectFactory.pointer(this); + uniffiTypeRoomEventSinkObjectFactory.freePointer(pointer); + uniffiTypeRoomEventSinkObjectFactory.unbless(ptr); + delete (this as any)[destructorGuardSymbol]; + } + } + + static instanceOf(obj_: any): obj_ is RoomEventSink { + return uniffiTypeRoomEventSinkObjectFactory.isConcreteType(obj_); + } + + +} + +const uniffiTypeRoomEventSinkObjectFactory: UniffiObjectFactory = (() => { + + /// + const registry = typeof FinalizationRegistry !== 'undefined' ? new FinalizationRegistry((heldValue: UniffiHandle) => { + uniffiTypeRoomEventSinkObjectFactory.freePointer(heldValue); + }) : null; + + return { + create(pointer: UniffiHandle): RoomEventSinkLike { + const instance = Object.create(RoomEventSink.prototype); + instance[pointerLiteralSymbol] = pointer; + instance[destructorGuardSymbol] = this.bless(pointer); + instance[uniffiTypeNameSymbol] = "RoomEventSink"; + return instance; + }, + + + bless(p: UniffiHandle): UniffiGcObject { + const ptr = { + p, // make sure this object doesn't get optimized away. + markDestroyed: () => undefined, + }; + if (registry) { + registry.register(ptr, p, ptr); + } + return ptr; + }, + + unbless(ptr_: UniffiGcObject) { + if (registry) { + registry.unregister(ptr_); + } + }, + + pointer(obj_: RoomEventSinkLike): UniffiHandle { + if ((obj_ as any)[destructorGuardSymbol] === undefined) { + throw new UniffiInternalError.UnexpectedNullPointer(); + } + return (obj_ as any)[pointerLiteralSymbol]; + }, + + clonePointer(obj_: RoomEventSinkLike): UniffiHandle { + const pointer = this.pointer(obj_); + return uniffiCaller.rustCall( + /*caller:*/ (callStatus) => nativeModule().ubrn_uniffi_matrix_rtc_fn_clone_roomeventsink(pointer, callStatus), + /*liftString:*/ FfiConverterString.lift + ); + }, + + freePointer(pointer: UniffiHandle): void { + uniffiCaller.rustCall( + /*caller:*/ (callStatus) => nativeModule().ubrn_uniffi_matrix_rtc_fn_free_roomeventsink(pointer, callStatus), + /*liftString:*/ FfiConverterString.lift + ); + }, + + isConcreteType(obj_: any): obj_ is RoomEventSinkLike { + return obj_[destructorGuardSymbol] && obj_[uniffiTypeNameSymbol] === "RoomEventSink"; + }, +}})(); +const FfiConverterTypeRoomEventSink = new FfiConverterObject(uniffiTypeRoomEventSinkObjectFactory); + +export interface ToDeviceSinkLike { + +/** + * A decrypted to-device message with its origin metadata. + * `sender_cross_signed` is the MSC4153 verdict on the sending device + * (`None` = the host cannot tell, treated as not signed: media keys + * from such devices are rejected unless configured otherwise). + */ + emit(eventType: string, sender: string, contentJson: string, origin: FfiEventOrigin, senderCrossSigned: boolean | undefined): boolean; +} +/** + * @deprecated Use `ToDeviceSinkLike` instead. + */ +export type ToDeviceSinkInterface = ToDeviceSinkLike; + + +export class ToDeviceSink extends UniffiAbstractObject implements ToDeviceSinkLike { + + readonly [uniffiTypeNameSymbol] = "ToDeviceSink"; + readonly [destructorGuardSymbol]: UniffiGcObject; + readonly [pointerLiteralSymbol]: UniffiHandle; + // No primary constructor declared for this class. +private constructor(pointer: UniffiHandle) { + super(); + this[pointerLiteralSymbol] = pointer; + this[destructorGuardSymbol] = uniffiTypeToDeviceSinkObjectFactory.bless(pointer); +} + + + + +/** + * A decrypted to-device message with its origin metadata. + * `sender_cross_signed` is the MSC4153 verdict on the sending device + * (`None` = the host cannot tell, treated as not signed: media keys + * from such devices are rejected unless configured otherwise). + */ + emit(eventType: string, sender: string, contentJson: string, origin: FfiEventOrigin, senderCrossSigned: boolean | undefined): boolean { + return FfiConverterBool.lift(uniffiCaller.rustCall( + /*caller:*/ (callStatus) => { + return nativeModule().ubrn_uniffi_matrix_rtc_fn_method_todevicesink_emit( + uniffiTypeToDeviceSinkObjectFactory.clonePointer(this), + FfiConverterString.lower(eventType, nativeModule().rustbuffer_alloc), + FfiConverterString.lower(sender, nativeModule().rustbuffer_alloc), + FfiConverterString.lower(contentJson, nativeModule().rustbuffer_alloc), + FfiConverterTypeFfiEventOrigin.lower(origin, nativeModule().rustbuffer_alloc), + FfiConverterOptionalBoolean.lower(senderCrossSigned, nativeModule().rustbuffer_alloc), + callStatus); + }, + /*liftString:*/ FfiConverterString.lift.bind(FfiConverterString), + )); + } + + + uniffiDestroy(): void { + const ptr = (this as any)[destructorGuardSymbol]; + if (ptr !== undefined) { + const pointer = uniffiTypeToDeviceSinkObjectFactory.pointer(this); + uniffiTypeToDeviceSinkObjectFactory.freePointer(pointer); + uniffiTypeToDeviceSinkObjectFactory.unbless(ptr); + delete (this as any)[destructorGuardSymbol]; + } + } + + static instanceOf(obj_: any): obj_ is ToDeviceSink { + return uniffiTypeToDeviceSinkObjectFactory.isConcreteType(obj_); + } + + +} + +const uniffiTypeToDeviceSinkObjectFactory: UniffiObjectFactory = (() => { + + /// + const registry = typeof FinalizationRegistry !== 'undefined' ? new FinalizationRegistry((heldValue: UniffiHandle) => { + uniffiTypeToDeviceSinkObjectFactory.freePointer(heldValue); + }) : null; + + return { + create(pointer: UniffiHandle): ToDeviceSinkLike { + const instance = Object.create(ToDeviceSink.prototype); + instance[pointerLiteralSymbol] = pointer; + instance[destructorGuardSymbol] = this.bless(pointer); + instance[uniffiTypeNameSymbol] = "ToDeviceSink"; + return instance; + }, + + + bless(p: UniffiHandle): UniffiGcObject { + const ptr = { + p, // make sure this object doesn't get optimized away. + markDestroyed: () => undefined, + }; + if (registry) { + registry.register(ptr, p, ptr); + } + return ptr; + }, + + unbless(ptr_: UniffiGcObject) { + if (registry) { + registry.unregister(ptr_); + } + }, + + pointer(obj_: ToDeviceSinkLike): UniffiHandle { + if ((obj_ as any)[destructorGuardSymbol] === undefined) { + throw new UniffiInternalError.UnexpectedNullPointer(); + } + return (obj_ as any)[pointerLiteralSymbol]; + }, + + clonePointer(obj_: ToDeviceSinkLike): UniffiHandle { + const pointer = this.pointer(obj_); + return uniffiCaller.rustCall( + /*caller:*/ (callStatus) => nativeModule().ubrn_uniffi_matrix_rtc_fn_clone_todevicesink(pointer, callStatus), + /*liftString:*/ FfiConverterString.lift + ); + }, + + freePointer(pointer: UniffiHandle): void { + uniffiCaller.rustCall( + /*caller:*/ (callStatus) => nativeModule().ubrn_uniffi_matrix_rtc_fn_free_todevicesink(pointer, callStatus), + /*liftString:*/ FfiConverterString.lift + ); + }, + + isConcreteType(obj_: any): obj_ is ToDeviceSinkLike { + return obj_[destructorGuardSymbol] && obj_[uniffiTypeNameSymbol] === "ToDeviceSink"; + }, +}})(); +const FfiConverterTypeToDeviceSink = new FfiConverterObject(uniffiTypeToDeviceSinkObjectFactory); + +export interface StateUpdateSinkLike { + +/** + * A batch of changed room-state events (applied atomically by the + * session: one snapshot per batch). State events are never encrypted, + * so their origin is `Cleartext`. + */ + emit(eventsJson: Array): boolean; +} +/** + * @deprecated Use `StateUpdateSinkLike` instead. + */ +export type StateUpdateSinkInterface = StateUpdateSinkLike; + + +export class StateUpdateSink extends UniffiAbstractObject implements StateUpdateSinkLike { + + readonly [uniffiTypeNameSymbol] = "StateUpdateSink"; + readonly [destructorGuardSymbol]: UniffiGcObject; + readonly [pointerLiteralSymbol]: UniffiHandle; + // No primary constructor declared for this class. +private constructor(pointer: UniffiHandle) { + super(); + this[pointerLiteralSymbol] = pointer; + this[destructorGuardSymbol] = uniffiTypeStateUpdateSinkObjectFactory.bless(pointer); +} + + + + +/** + * A batch of changed room-state events (applied atomically by the + * session: one snapshot per batch). State events are never encrypted, + * so their origin is `Cleartext`. + */ + emit(eventsJson: Array): boolean { + return FfiConverterBool.lift(uniffiCaller.rustCall( + /*caller:*/ (callStatus) => { + return nativeModule().ubrn_uniffi_matrix_rtc_fn_method_stateupdatesink_emit( + uniffiTypeStateUpdateSinkObjectFactory.clonePointer(this), + FfiConverterSequenceString.lower(eventsJson, nativeModule().rustbuffer_alloc), + callStatus); + }, + /*liftString:*/ FfiConverterString.lift.bind(FfiConverterString), + )); + } + + + uniffiDestroy(): void { + const ptr = (this as any)[destructorGuardSymbol]; + if (ptr !== undefined) { + const pointer = uniffiTypeStateUpdateSinkObjectFactory.pointer(this); + uniffiTypeStateUpdateSinkObjectFactory.freePointer(pointer); + uniffiTypeStateUpdateSinkObjectFactory.unbless(ptr); + delete (this as any)[destructorGuardSymbol]; + } + } + + static instanceOf(obj_: any): obj_ is StateUpdateSink { + return uniffiTypeStateUpdateSinkObjectFactory.isConcreteType(obj_); + } + + +} + +const uniffiTypeStateUpdateSinkObjectFactory: UniffiObjectFactory = (() => { + + /// + const registry = typeof FinalizationRegistry !== 'undefined' ? new FinalizationRegistry((heldValue: UniffiHandle) => { + uniffiTypeStateUpdateSinkObjectFactory.freePointer(heldValue); + }) : null; + + return { + create(pointer: UniffiHandle): StateUpdateSinkLike { + const instance = Object.create(StateUpdateSink.prototype); + instance[pointerLiteralSymbol] = pointer; + instance[destructorGuardSymbol] = this.bless(pointer); + instance[uniffiTypeNameSymbol] = "StateUpdateSink"; + return instance; + }, + + + bless(p: UniffiHandle): UniffiGcObject { + const ptr = { + p, // make sure this object doesn't get optimized away. + markDestroyed: () => undefined, + }; + if (registry) { + registry.register(ptr, p, ptr); + } + return ptr; + }, + + unbless(ptr_: UniffiGcObject) { + if (registry) { + registry.unregister(ptr_); + } + }, + + pointer(obj_: StateUpdateSinkLike): UniffiHandle { + if ((obj_ as any)[destructorGuardSymbol] === undefined) { + throw new UniffiInternalError.UnexpectedNullPointer(); + } + return (obj_ as any)[pointerLiteralSymbol]; + }, + + clonePointer(obj_: StateUpdateSinkLike): UniffiHandle { + const pointer = this.pointer(obj_); + return uniffiCaller.rustCall( + /*caller:*/ (callStatus) => nativeModule().ubrn_uniffi_matrix_rtc_fn_clone_stateupdatesink(pointer, callStatus), + /*liftString:*/ FfiConverterString.lift + ); + }, + + freePointer(pointer: UniffiHandle): void { + uniffiCaller.rustCall( + /*caller:*/ (callStatus) => nativeModule().ubrn_uniffi_matrix_rtc_fn_free_stateupdatesink(pointer, callStatus), + /*liftString:*/ FfiConverterString.lift + ); + }, + + isConcreteType(obj_: any): obj_ is StateUpdateSinkLike { + return obj_[destructorGuardSymbol] && obj_[uniffiTypeNameSymbol] === "StateUpdateSink"; + }, +}})(); +const FfiConverterTypeStateUpdateSink = new FfiConverterObject(uniffiTypeStateUpdateSinkObjectFactory); + +/** + * The host-implemented Matrix driver: the same seam as + * [`crate::driver::MatrixDriver`], flattened for FFI. matrix-rust-sdk hosts + * adapt their `MatrixDriver`; a matrix-js-sdk host implements this directly. + * + * Inbound events are a driver job too: the `subscribe_*` methods hand the + * host a sink to emit into. Each is called synchronously, **exactly once**, + * during [`FfiMatrixDriver`] construction — store the sink and hook the + * actual event handlers whenever convenient afterwards. Single-sink + * semantics: fan-out to multiple managers happens on the Rust side. + * + * (`async_trait` must sit *under* the uniffi attribute: uniffi parses the + * original `async fn` tokens.) + */ +export interface MatrixDriverCallback { + + sendStickyEvent(roomId: string, eventType: string, contentJson: string, durationMs: bigint, asyncOpts_?: { signal: AbortSignal }) /*throws*/: Promise; + sendStateEvent(roomId: string, eventType: string, stateKey: string, contentJson: string, asyncOpts_?: { signal: AbortSignal }) /*throws*/: Promise; +/** + * Returns the MSC4140 delay id (not an event id). `sticky_duration_ms` + * makes it a delayed *sticky* event (MSC4354 + MSC4140); ignore it if + * the host SDK cannot express both yet. + */ + sendDelayedEvent(roomId: string, eventType: string, contentJson: string, delayMs: bigint, stickyDurationMs: bigint | undefined, asyncOpts_?: { signal: AbortSignal }) /*throws*/: Promise; +/** + * Delayed state event — compat only (`StateEvents`). + */ + sendDelayedStateEvent(roomId: string, eventType: string, stateKey: string, contentJson: string, delayMs: bigint, asyncOpts_?: { signal: AbortSignal }) /*throws*/: Promise; + restartDelayedEvent(roomId: string, delayId: string, asyncOpts_?: { signal: AbortSignal }) /*throws*/: Promise; + cancelDelayedEvent(roomId: string, delayId: string, asyncOpts_?: { signal: AbortSignal }) /*throws*/: Promise; +/** + * MSC4195: hand the delayed leave to the SFU. `livekit_service_url` is + * the transport we publish on (`None` for a receive-only member) and + * `delay_ms` the armed delay — what an adapter that delegates through + * the authorisation service's token endpoint needs. + */ + delegateLivekitDelayedLeave(roomId: string, slotId: string, memberJson: string, delayId: string, livekitServiceUrl: string | undefined, delayMs: bigint, asyncOpts_?: { signal: AbortSignal }) /*throws*/: Promise; + sendToDevice(recipients: Array, eventType: string, contentJson: string, asyncOpts_?: { signal: AbortSignal }) /*throws*/: Promise>; +/** + * `GET /_matrix/client/v1/rtc/transports`, with well-known fallback. + */ + getRtcTransports(asyncOpts_?: { signal: AbortSignal }) /*throws*/: Promise>; +/** + * MSC4195 token exchange, OpenID token included (see + * [`FfiLivekitTokenRequest`]). + */ + getLivekitToken(request: FfiLivekitTokenRequest, asyncOpts_?: { signal: AbortSignal }) /*throws*/: Promise; +/** + * Latest `limit` timeline events of `event_type`, as JSON strings. + */ + readEvents(eventType: string, stateKey: string | undefined, limit: number, asyncOpts_?: { signal: AbortSignal }) /*throws*/: Promise>; +/** + * Current state entries of `event_type` (`state_key: None` = any). + */ + readState(eventType: string, stateKey: string | undefined, asyncOpts_?: { signal: AbortSignal }) /*throws*/: Promise>; +/** + * Live room events (sticky member events, slot/state changes). Store + * the sink; call `emit` from the host SDK's event handlers. + */ + subscribeRoomEvents(sink: RoomEventSinkLike): void; +/** + * Decrypted inbound to-device events with origin metadata. + */ + subscribeToDeviceEvents(sink: ToDeviceSinkLike): void; +/** + * Room-state update batches (what notices a slot closing promptly). + */ + subscribeStateUpdates(sink: StateUpdateSinkLike): void; +/** + * Whether the homeserver is reachable right now (a syncing client: its + * sync loop is running). + */ + isHomeserverConnected(): boolean; +/** + * Live connectivity verdicts. Store the sink; `emit` the new value from + * the host SDK's sync-state handler. + */ + subscribeConnectivity(sink: ConnectivitySinkLike): void; +} + + +/** + * The host-implemented Matrix driver: the same seam as + * [`crate::driver::MatrixDriver`], flattened for FFI. matrix-rust-sdk hosts + * adapt their `MatrixDriver`; a matrix-js-sdk host implements this directly. + * + * Inbound events are a driver job too: the `subscribe_*` methods hand the + * host a sink to emit into. Each is called synchronously, **exactly once**, + * during [`FfiMatrixDriver`] construction — store the sink and hook the + * actual event handlers whenever convenient afterwards. Single-sink + * semantics: fan-out to multiple managers happens on the Rust side. + * + * (`async_trait` must sit *under* the uniffi attribute: uniffi parses the + * original `async fn` tokens.) + */ +export class MatrixDriverCallbackImpl extends UniffiAbstractObject implements MatrixDriverCallback { + + readonly [uniffiTypeNameSymbol] = "MatrixDriverCallbackImpl"; + readonly [destructorGuardSymbol]: UniffiGcObject; + readonly [pointerLiteralSymbol]: UniffiHandle; + // No primary constructor declared for this class. +private constructor(pointer: UniffiHandle) { + super(); + this[pointerLiteralSymbol] = pointer; + this[destructorGuardSymbol] = uniffiTypeMatrixDriverCallbackImplObjectFactory.bless(pointer); +} + + + + + async sendStickyEvent(roomId: string, eventType: string, contentJson: string, durationMs: bigint, asyncOpts_?: { signal: AbortSignal }): Promise /*throws*/ { + return await uniffiRustCallAsync( + /*rustCaller:*/ uniffiCaller, + /*rustFutureFunc:*/ () => { + return nativeModule().ubrn_uniffi_matrix_rtc_fn_method_matrixdrivercallback_send_sticky_event( + uniffiTypeMatrixDriverCallbackImplObjectFactory.clonePointer(this),FfiConverterString.lower(roomId, nativeModule().rustbuffer_alloc),FfiConverterString.lower(eventType, nativeModule().rustbuffer_alloc),FfiConverterString.lower(contentJson, nativeModule().rustbuffer_alloc),FfiConverterUInt64.lower(durationMs, nativeModule().rustbuffer_alloc) + ); + }, + /*pollFunc:*/ nativeModule().ubrn_ffi_matrix_rtc_rust_future_poll_rust_buffer, + /*cancelFunc:*/ nativeModule().ubrn_ffi_matrix_rtc_rust_future_cancel_rust_buffer, + /*completeFunc:*/ nativeModule().ubrn_ffi_matrix_rtc_rust_future_complete_rust_buffer, + /*freeFunc:*/ nativeModule().ubrn_ffi_matrix_rtc_rust_future_free_rust_buffer, + // Async returns always go through the JS-side converter: the + // FFI symbol returns the future handle (u64), and the user-level + // RustBuffer comes back via the shared `rust_future_complete_*` + // export. The bytes the runtime hands back must be deserialized + // here using the per-callable return-type converter. + // Borrowed view over foreign memory: the call site owns the free, + // as on the sync paths. Unconditional — a no-op where buffers are + // already JS-owned. + /*liftFunc:*/ (__rb) => { + try { + return FfiConverterTypeFfiSendEventResponse.lift(__rb); + } finally { + nativeModule().rustbuffer_free(__rb); + } + }, + /*liftString:*/ FfiConverterString.lift.bind(FfiConverterString), + /*asyncOpts:*/ asyncOpts_, + /*errorHandler:*/ FfiConverterTypeRtcError.lift.bind(FfiConverterTypeRtcError) + ); + } + + async sendStateEvent(roomId: string, eventType: string, stateKey: string, contentJson: string, asyncOpts_?: { signal: AbortSignal }): Promise /*throws*/ { + return await uniffiRustCallAsync( + /*rustCaller:*/ uniffiCaller, + /*rustFutureFunc:*/ () => { + return nativeModule().ubrn_uniffi_matrix_rtc_fn_method_matrixdrivercallback_send_state_event( + uniffiTypeMatrixDriverCallbackImplObjectFactory.clonePointer(this),FfiConverterString.lower(roomId, nativeModule().rustbuffer_alloc),FfiConverterString.lower(eventType, nativeModule().rustbuffer_alloc),FfiConverterString.lower(stateKey, nativeModule().rustbuffer_alloc),FfiConverterString.lower(contentJson, nativeModule().rustbuffer_alloc) + ); + }, + /*pollFunc:*/ nativeModule().ubrn_ffi_matrix_rtc_rust_future_poll_rust_buffer, + /*cancelFunc:*/ nativeModule().ubrn_ffi_matrix_rtc_rust_future_cancel_rust_buffer, + /*completeFunc:*/ nativeModule().ubrn_ffi_matrix_rtc_rust_future_complete_rust_buffer, + /*freeFunc:*/ nativeModule().ubrn_ffi_matrix_rtc_rust_future_free_rust_buffer, + // Async returns always go through the JS-side converter: the + // FFI symbol returns the future handle (u64), and the user-level + // RustBuffer comes back via the shared `rust_future_complete_*` + // export. The bytes the runtime hands back must be deserialized + // here using the per-callable return-type converter. + // Borrowed view over foreign memory: the call site owns the free, + // as on the sync paths. Unconditional — a no-op where buffers are + // already JS-owned. + /*liftFunc:*/ (__rb) => { + try { + return FfiConverterTypeFfiSendEventResponse.lift(__rb); + } finally { + nativeModule().rustbuffer_free(__rb); + } + }, + /*liftString:*/ FfiConverterString.lift.bind(FfiConverterString), + /*asyncOpts:*/ asyncOpts_, + /*errorHandler:*/ FfiConverterTypeRtcError.lift.bind(FfiConverterTypeRtcError) + ); + } + +/** + * Returns the MSC4140 delay id (not an event id). `sticky_duration_ms` + * makes it a delayed *sticky* event (MSC4354 + MSC4140); ignore it if + * the host SDK cannot express both yet. + */ + async sendDelayedEvent(roomId: string, eventType: string, contentJson: string, delayMs: bigint, stickyDurationMs: bigint | undefined, asyncOpts_?: { signal: AbortSignal }): Promise /*throws*/ { + return await uniffiRustCallAsync( + /*rustCaller:*/ uniffiCaller, + /*rustFutureFunc:*/ () => { + return nativeModule().ubrn_uniffi_matrix_rtc_fn_method_matrixdrivercallback_send_delayed_event( + uniffiTypeMatrixDriverCallbackImplObjectFactory.clonePointer(this),FfiConverterString.lower(roomId, nativeModule().rustbuffer_alloc),FfiConverterString.lower(eventType, nativeModule().rustbuffer_alloc),FfiConverterString.lower(contentJson, nativeModule().rustbuffer_alloc),FfiConverterUInt64.lower(delayMs, nativeModule().rustbuffer_alloc),FfiConverterOptionalUInt64.lower(stickyDurationMs, nativeModule().rustbuffer_alloc) + ); + }, + /*pollFunc:*/ nativeModule().ubrn_ffi_matrix_rtc_rust_future_poll_rust_buffer, + /*cancelFunc:*/ nativeModule().ubrn_ffi_matrix_rtc_rust_future_cancel_rust_buffer, + /*completeFunc:*/ nativeModule().ubrn_ffi_matrix_rtc_rust_future_complete_rust_buffer, + /*freeFunc:*/ nativeModule().ubrn_ffi_matrix_rtc_rust_future_free_rust_buffer, + // Async returns always go through the JS-side converter: the + // FFI symbol returns the future handle (u64), and the user-level + // RustBuffer comes back via the shared `rust_future_complete_*` + // export. The bytes the runtime hands back must be deserialized + // here using the per-callable return-type converter. + // Borrowed view over foreign memory: the call site owns the free, + // as on the sync paths. Unconditional — a no-op where buffers are + // already JS-owned. + /*liftFunc:*/ (__rb) => { + try { + return FfiConverterString.lift(__rb); + } finally { + nativeModule().rustbuffer_free(__rb); + } + }, + /*liftString:*/ FfiConverterString.lift.bind(FfiConverterString), + /*asyncOpts:*/ asyncOpts_, + /*errorHandler:*/ FfiConverterTypeRtcError.lift.bind(FfiConverterTypeRtcError) + ); + } + +/** + * Delayed state event — compat only (`StateEvents`). + */ + async sendDelayedStateEvent(roomId: string, eventType: string, stateKey: string, contentJson: string, delayMs: bigint, asyncOpts_?: { signal: AbortSignal }): Promise /*throws*/ { + return await uniffiRustCallAsync( + /*rustCaller:*/ uniffiCaller, + /*rustFutureFunc:*/ () => { + return nativeModule().ubrn_uniffi_matrix_rtc_fn_method_matrixdrivercallback_send_delayed_state_event( + uniffiTypeMatrixDriverCallbackImplObjectFactory.clonePointer(this),FfiConverterString.lower(roomId, nativeModule().rustbuffer_alloc),FfiConverterString.lower(eventType, nativeModule().rustbuffer_alloc),FfiConverterString.lower(stateKey, nativeModule().rustbuffer_alloc),FfiConverterString.lower(contentJson, nativeModule().rustbuffer_alloc),FfiConverterUInt64.lower(delayMs, nativeModule().rustbuffer_alloc) + ); + }, + /*pollFunc:*/ nativeModule().ubrn_ffi_matrix_rtc_rust_future_poll_rust_buffer, + /*cancelFunc:*/ nativeModule().ubrn_ffi_matrix_rtc_rust_future_cancel_rust_buffer, + /*completeFunc:*/ nativeModule().ubrn_ffi_matrix_rtc_rust_future_complete_rust_buffer, + /*freeFunc:*/ nativeModule().ubrn_ffi_matrix_rtc_rust_future_free_rust_buffer, + // Async returns always go through the JS-side converter: the + // FFI symbol returns the future handle (u64), and the user-level + // RustBuffer comes back via the shared `rust_future_complete_*` + // export. The bytes the runtime hands back must be deserialized + // here using the per-callable return-type converter. + // Borrowed view over foreign memory: the call site owns the free, + // as on the sync paths. Unconditional — a no-op where buffers are + // already JS-owned. + /*liftFunc:*/ (__rb) => { + try { + return FfiConverterString.lift(__rb); + } finally { + nativeModule().rustbuffer_free(__rb); + } + }, + /*liftString:*/ FfiConverterString.lift.bind(FfiConverterString), + /*asyncOpts:*/ asyncOpts_, + /*errorHandler:*/ FfiConverterTypeRtcError.lift.bind(FfiConverterTypeRtcError) + ); + } + + async restartDelayedEvent(roomId: string, delayId: string, asyncOpts_?: { signal: AbortSignal }): Promise /*throws*/ { + return await uniffiRustCallAsync( + /*rustCaller:*/ uniffiCaller, + /*rustFutureFunc:*/ () => { + return nativeModule().ubrn_uniffi_matrix_rtc_fn_method_matrixdrivercallback_restart_delayed_event( + uniffiTypeMatrixDriverCallbackImplObjectFactory.clonePointer(this),FfiConverterString.lower(roomId, nativeModule().rustbuffer_alloc),FfiConverterString.lower(delayId, nativeModule().rustbuffer_alloc) + ); + }, + /*pollFunc:*/ nativeModule().ubrn_ffi_matrix_rtc_rust_future_poll_void, + /*cancelFunc:*/ nativeModule().ubrn_ffi_matrix_rtc_rust_future_cancel_void, + /*completeFunc:*/ nativeModule().ubrn_ffi_matrix_rtc_rust_future_complete_void, + /*freeFunc:*/ nativeModule().ubrn_ffi_matrix_rtc_rust_future_free_void, + /*liftFunc:*/ (_v) => {}, + /*liftString:*/ FfiConverterString.lift.bind(FfiConverterString), + /*asyncOpts:*/ asyncOpts_, + /*errorHandler:*/ FfiConverterTypeRtcError.lift.bind(FfiConverterTypeRtcError) + ); + } + + async cancelDelayedEvent(roomId: string, delayId: string, asyncOpts_?: { signal: AbortSignal }): Promise /*throws*/ { + return await uniffiRustCallAsync( + /*rustCaller:*/ uniffiCaller, + /*rustFutureFunc:*/ () => { + return nativeModule().ubrn_uniffi_matrix_rtc_fn_method_matrixdrivercallback_cancel_delayed_event( + uniffiTypeMatrixDriverCallbackImplObjectFactory.clonePointer(this),FfiConverterString.lower(roomId, nativeModule().rustbuffer_alloc),FfiConverterString.lower(delayId, nativeModule().rustbuffer_alloc) + ); + }, + /*pollFunc:*/ nativeModule().ubrn_ffi_matrix_rtc_rust_future_poll_void, + /*cancelFunc:*/ nativeModule().ubrn_ffi_matrix_rtc_rust_future_cancel_void, + /*completeFunc:*/ nativeModule().ubrn_ffi_matrix_rtc_rust_future_complete_void, + /*freeFunc:*/ nativeModule().ubrn_ffi_matrix_rtc_rust_future_free_void, + /*liftFunc:*/ (_v) => {}, + /*liftString:*/ FfiConverterString.lift.bind(FfiConverterString), + /*asyncOpts:*/ asyncOpts_, + /*errorHandler:*/ FfiConverterTypeRtcError.lift.bind(FfiConverterTypeRtcError) + ); + } + +/** + * MSC4195: hand the delayed leave to the SFU. `livekit_service_url` is + * the transport we publish on (`None` for a receive-only member) and + * `delay_ms` the armed delay — what an adapter that delegates through + * the authorisation service's token endpoint needs. + */ + async delegateLivekitDelayedLeave(roomId: string, slotId: string, memberJson: string, delayId: string, livekitServiceUrl: string | undefined, delayMs: bigint, asyncOpts_?: { signal: AbortSignal }): Promise /*throws*/ { + return await uniffiRustCallAsync( + /*rustCaller:*/ uniffiCaller, + /*rustFutureFunc:*/ () => { + return nativeModule().ubrn_uniffi_matrix_rtc_fn_method_matrixdrivercallback_delegate_livekit_delayed_leave( + uniffiTypeMatrixDriverCallbackImplObjectFactory.clonePointer(this),FfiConverterString.lower(roomId, nativeModule().rustbuffer_alloc),FfiConverterString.lower(slotId, nativeModule().rustbuffer_alloc),FfiConverterString.lower(memberJson, nativeModule().rustbuffer_alloc),FfiConverterString.lower(delayId, nativeModule().rustbuffer_alloc),FfiConverterOptionalString.lower(livekitServiceUrl, nativeModule().rustbuffer_alloc),FfiConverterUInt64.lower(delayMs, nativeModule().rustbuffer_alloc) + ); + }, + /*pollFunc:*/ nativeModule().ubrn_ffi_matrix_rtc_rust_future_poll_void, + /*cancelFunc:*/ nativeModule().ubrn_ffi_matrix_rtc_rust_future_cancel_void, + /*completeFunc:*/ nativeModule().ubrn_ffi_matrix_rtc_rust_future_complete_void, + /*freeFunc:*/ nativeModule().ubrn_ffi_matrix_rtc_rust_future_free_void, + /*liftFunc:*/ (_v) => {}, + /*liftString:*/ FfiConverterString.lift.bind(FfiConverterString), + /*asyncOpts:*/ asyncOpts_, + /*errorHandler:*/ FfiConverterTypeRtcError.lift.bind(FfiConverterTypeRtcError) + ); + } + + async sendToDevice(recipients: Array, eventType: string, contentJson: string, asyncOpts_?: { signal: AbortSignal }): Promise> /*throws*/ { + return await uniffiRustCallAsync( + /*rustCaller:*/ uniffiCaller, + /*rustFutureFunc:*/ () => { + return nativeModule().ubrn_uniffi_matrix_rtc_fn_method_matrixdrivercallback_send_to_device( + uniffiTypeMatrixDriverCallbackImplObjectFactory.clonePointer(this),FfiConverterSequenceTypeFfiToDeviceRecipient.lower(recipients, nativeModule().rustbuffer_alloc),FfiConverterString.lower(eventType, nativeModule().rustbuffer_alloc),FfiConverterString.lower(contentJson, nativeModule().rustbuffer_alloc) + ); + }, + /*pollFunc:*/ nativeModule().ubrn_ffi_matrix_rtc_rust_future_poll_rust_buffer, + /*cancelFunc:*/ nativeModule().ubrn_ffi_matrix_rtc_rust_future_cancel_rust_buffer, + /*completeFunc:*/ nativeModule().ubrn_ffi_matrix_rtc_rust_future_complete_rust_buffer, + /*freeFunc:*/ nativeModule().ubrn_ffi_matrix_rtc_rust_future_free_rust_buffer, + // Async returns always go through the JS-side converter: the + // FFI symbol returns the future handle (u64), and the user-level + // RustBuffer comes back via the shared `rust_future_complete_*` + // export. The bytes the runtime hands back must be deserialized + // here using the per-callable return-type converter. + // Borrowed view over foreign memory: the call site owns the free, + // as on the sync paths. Unconditional — a no-op where buffers are + // already JS-owned. + /*liftFunc:*/ (__rb) => { + try { + return FfiConverterSequenceTypeFfiToDeviceDelivery.lift(__rb); + } finally { + nativeModule().rustbuffer_free(__rb); + } + }, + /*liftString:*/ FfiConverterString.lift.bind(FfiConverterString), + /*asyncOpts:*/ asyncOpts_, + /*errorHandler:*/ FfiConverterTypeRtcError.lift.bind(FfiConverterTypeRtcError) + ); + } + +/** + * `GET /_matrix/client/v1/rtc/transports`, with well-known fallback. + */ + async getRtcTransports(asyncOpts_?: { signal: AbortSignal }): Promise> /*throws*/ { + return await uniffiRustCallAsync( + /*rustCaller:*/ uniffiCaller, + /*rustFutureFunc:*/ () => { + return nativeModule().ubrn_uniffi_matrix_rtc_fn_method_matrixdrivercallback_get_rtc_transports( + uniffiTypeMatrixDriverCallbackImplObjectFactory.clonePointer(this) + ); + }, + /*pollFunc:*/ nativeModule().ubrn_ffi_matrix_rtc_rust_future_poll_rust_buffer, + /*cancelFunc:*/ nativeModule().ubrn_ffi_matrix_rtc_rust_future_cancel_rust_buffer, + /*completeFunc:*/ nativeModule().ubrn_ffi_matrix_rtc_rust_future_complete_rust_buffer, + /*freeFunc:*/ nativeModule().ubrn_ffi_matrix_rtc_rust_future_free_rust_buffer, + // Async returns always go through the JS-side converter: the + // FFI symbol returns the future handle (u64), and the user-level + // RustBuffer comes back via the shared `rust_future_complete_*` + // export. The bytes the runtime hands back must be deserialized + // here using the per-callable return-type converter. + // Borrowed view over foreign memory: the call site owns the free, + // as on the sync paths. Unconditional — a no-op where buffers are + // already JS-owned. + /*liftFunc:*/ (__rb) => { + try { + return FfiConverterSequenceTypeFfiRtcTransport.lift(__rb); + } finally { + nativeModule().rustbuffer_free(__rb); + } + }, + /*liftString:*/ FfiConverterString.lift.bind(FfiConverterString), + /*asyncOpts:*/ asyncOpts_, + /*errorHandler:*/ FfiConverterTypeRtcError.lift.bind(FfiConverterTypeRtcError) + ); + } + +/** + * MSC4195 token exchange, OpenID token included (see + * [`FfiLivekitTokenRequest`]). + */ + async getLivekitToken(request: FfiLivekitTokenRequest, asyncOpts_?: { signal: AbortSignal }): Promise /*throws*/ { + return await uniffiRustCallAsync( + /*rustCaller:*/ uniffiCaller, + /*rustFutureFunc:*/ () => { + return nativeModule().ubrn_uniffi_matrix_rtc_fn_method_matrixdrivercallback_get_livekit_token( + uniffiTypeMatrixDriverCallbackImplObjectFactory.clonePointer(this),FfiConverterTypeFfiLivekitTokenRequest.lower(request, nativeModule().rustbuffer_alloc) + ); + }, + /*pollFunc:*/ nativeModule().ubrn_ffi_matrix_rtc_rust_future_poll_rust_buffer, + /*cancelFunc:*/ nativeModule().ubrn_ffi_matrix_rtc_rust_future_cancel_rust_buffer, + /*completeFunc:*/ nativeModule().ubrn_ffi_matrix_rtc_rust_future_complete_rust_buffer, + /*freeFunc:*/ nativeModule().ubrn_ffi_matrix_rtc_rust_future_free_rust_buffer, + // Async returns always go through the JS-side converter: the + // FFI symbol returns the future handle (u64), and the user-level + // RustBuffer comes back via the shared `rust_future_complete_*` + // export. The bytes the runtime hands back must be deserialized + // here using the per-callable return-type converter. + // Borrowed view over foreign memory: the call site owns the free, + // as on the sync paths. Unconditional — a no-op where buffers are + // already JS-owned. + /*liftFunc:*/ (__rb) => { + try { + return FfiConverterTypeFfiLivekitToken.lift(__rb); + } finally { + nativeModule().rustbuffer_free(__rb); + } + }, + /*liftString:*/ FfiConverterString.lift.bind(FfiConverterString), + /*asyncOpts:*/ asyncOpts_, + /*errorHandler:*/ FfiConverterTypeRtcError.lift.bind(FfiConverterTypeRtcError) + ); + } + +/** + * Latest `limit` timeline events of `event_type`, as JSON strings. + */ + async readEvents(eventType: string, stateKey: string | undefined, limit: number, asyncOpts_?: { signal: AbortSignal }): Promise> /*throws*/ { + return await uniffiRustCallAsync( + /*rustCaller:*/ uniffiCaller, + /*rustFutureFunc:*/ () => { + return nativeModule().ubrn_uniffi_matrix_rtc_fn_method_matrixdrivercallback_read_events( + uniffiTypeMatrixDriverCallbackImplObjectFactory.clonePointer(this),FfiConverterString.lower(eventType, nativeModule().rustbuffer_alloc),FfiConverterOptionalString.lower(stateKey, nativeModule().rustbuffer_alloc),FfiConverterUInt32.lower(limit, nativeModule().rustbuffer_alloc) + ); + }, + /*pollFunc:*/ nativeModule().ubrn_ffi_matrix_rtc_rust_future_poll_rust_buffer, + /*cancelFunc:*/ nativeModule().ubrn_ffi_matrix_rtc_rust_future_cancel_rust_buffer, + /*completeFunc:*/ nativeModule().ubrn_ffi_matrix_rtc_rust_future_complete_rust_buffer, + /*freeFunc:*/ nativeModule().ubrn_ffi_matrix_rtc_rust_future_free_rust_buffer, + // Async returns always go through the JS-side converter: the + // FFI symbol returns the future handle (u64), and the user-level + // RustBuffer comes back via the shared `rust_future_complete_*` + // export. The bytes the runtime hands back must be deserialized + // here using the per-callable return-type converter. + // Borrowed view over foreign memory: the call site owns the free, + // as on the sync paths. Unconditional — a no-op where buffers are + // already JS-owned. + /*liftFunc:*/ (__rb) => { + try { + return FfiConverterSequenceString.lift(__rb); + } finally { + nativeModule().rustbuffer_free(__rb); + } + }, + /*liftString:*/ FfiConverterString.lift.bind(FfiConverterString), + /*asyncOpts:*/ asyncOpts_, + /*errorHandler:*/ FfiConverterTypeRtcError.lift.bind(FfiConverterTypeRtcError) + ); + } + +/** + * Current state entries of `event_type` (`state_key: None` = any). + */ + async readState(eventType: string, stateKey: string | undefined, asyncOpts_?: { signal: AbortSignal }): Promise> /*throws*/ { + return await uniffiRustCallAsync( + /*rustCaller:*/ uniffiCaller, + /*rustFutureFunc:*/ () => { + return nativeModule().ubrn_uniffi_matrix_rtc_fn_method_matrixdrivercallback_read_state( + uniffiTypeMatrixDriverCallbackImplObjectFactory.clonePointer(this),FfiConverterString.lower(eventType, nativeModule().rustbuffer_alloc),FfiConverterOptionalString.lower(stateKey, nativeModule().rustbuffer_alloc) + ); + }, + /*pollFunc:*/ nativeModule().ubrn_ffi_matrix_rtc_rust_future_poll_rust_buffer, + /*cancelFunc:*/ nativeModule().ubrn_ffi_matrix_rtc_rust_future_cancel_rust_buffer, + /*completeFunc:*/ nativeModule().ubrn_ffi_matrix_rtc_rust_future_complete_rust_buffer, + /*freeFunc:*/ nativeModule().ubrn_ffi_matrix_rtc_rust_future_free_rust_buffer, + // Async returns always go through the JS-side converter: the + // FFI symbol returns the future handle (u64), and the user-level + // RustBuffer comes back via the shared `rust_future_complete_*` + // export. The bytes the runtime hands back must be deserialized + // here using the per-callable return-type converter. + // Borrowed view over foreign memory: the call site owns the free, + // as on the sync paths. Unconditional — a no-op where buffers are + // already JS-owned. + /*liftFunc:*/ (__rb) => { + try { + return FfiConverterSequenceString.lift(__rb); + } finally { + nativeModule().rustbuffer_free(__rb); + } + }, + /*liftString:*/ FfiConverterString.lift.bind(FfiConverterString), + /*asyncOpts:*/ asyncOpts_, + /*errorHandler:*/ FfiConverterTypeRtcError.lift.bind(FfiConverterTypeRtcError) + ); + } + +/** + * Live room events (sticky member events, slot/state changes). Store + * the sink; call `emit` from the host SDK's event handlers. + */ + subscribeRoomEvents(sink: RoomEventSinkLike): void {uniffiCaller.rustCall( + /*caller:*/ (callStatus) => { nativeModule().ubrn_uniffi_matrix_rtc_fn_method_matrixdrivercallback_subscribe_room_events( + uniffiTypeMatrixDriverCallbackImplObjectFactory.clonePointer(this), + FfiConverterTypeRoomEventSink.lower(sink, nativeModule().rustbuffer_alloc), + callStatus); + }, + /*liftString:*/ FfiConverterString.lift.bind(FfiConverterString), + ); + } + +/** + * Decrypted inbound to-device events with origin metadata. + */ + subscribeToDeviceEvents(sink: ToDeviceSinkLike): void {uniffiCaller.rustCall( + /*caller:*/ (callStatus) => { nativeModule().ubrn_uniffi_matrix_rtc_fn_method_matrixdrivercallback_subscribe_to_device_events( + uniffiTypeMatrixDriverCallbackImplObjectFactory.clonePointer(this), + FfiConverterTypeToDeviceSink.lower(sink, nativeModule().rustbuffer_alloc), + callStatus); + }, + /*liftString:*/ FfiConverterString.lift.bind(FfiConverterString), + ); + } + +/** + * Room-state update batches (what notices a slot closing promptly). + */ + subscribeStateUpdates(sink: StateUpdateSinkLike): void {uniffiCaller.rustCall( + /*caller:*/ (callStatus) => { nativeModule().ubrn_uniffi_matrix_rtc_fn_method_matrixdrivercallback_subscribe_state_updates( + uniffiTypeMatrixDriverCallbackImplObjectFactory.clonePointer(this), + FfiConverterTypeStateUpdateSink.lower(sink, nativeModule().rustbuffer_alloc), + callStatus); + }, + /*liftString:*/ FfiConverterString.lift.bind(FfiConverterString), + ); + } + +/** + * Whether the homeserver is reachable right now (a syncing client: its + * sync loop is running). + */ + isHomeserverConnected(): boolean { + return FfiConverterBool.lift(uniffiCaller.rustCall( + /*caller:*/ (callStatus) => { + return nativeModule().ubrn_uniffi_matrix_rtc_fn_method_matrixdrivercallback_is_homeserver_connected( + uniffiTypeMatrixDriverCallbackImplObjectFactory.clonePointer(this), + callStatus); + }, + /*liftString:*/ FfiConverterString.lift.bind(FfiConverterString), + )); + } + +/** + * Live connectivity verdicts. Store the sink; `emit` the new value from + * the host SDK's sync-state handler. + */ + subscribeConnectivity(sink: ConnectivitySinkLike): void {uniffiCaller.rustCall( + /*caller:*/ (callStatus) => { nativeModule().ubrn_uniffi_matrix_rtc_fn_method_matrixdrivercallback_subscribe_connectivity( + uniffiTypeMatrixDriverCallbackImplObjectFactory.clonePointer(this), + FfiConverterTypeConnectivitySink.lower(sink, nativeModule().rustbuffer_alloc), + callStatus); + }, + /*liftString:*/ FfiConverterString.lift.bind(FfiConverterString), + ); + } + + + uniffiDestroy(): void { + const ptr = (this as any)[destructorGuardSymbol]; + if (ptr !== undefined) { + const pointer = uniffiTypeMatrixDriverCallbackImplObjectFactory.pointer(this); + uniffiTypeMatrixDriverCallbackImplObjectFactory.freePointer(pointer); + uniffiTypeMatrixDriverCallbackImplObjectFactory.unbless(ptr); + delete (this as any)[destructorGuardSymbol]; + } + } + + static instanceOf(obj_: any): obj_ is MatrixDriverCallbackImpl { + return uniffiTypeMatrixDriverCallbackImplObjectFactory.isConcreteType(obj_); + } + + +} + +const uniffiTypeMatrixDriverCallbackImplObjectFactory: UniffiObjectFactory = (() => { + + /// + const registry = typeof FinalizationRegistry !== 'undefined' ? new FinalizationRegistry((heldValue: UniffiHandle) => { + uniffiTypeMatrixDriverCallbackImplObjectFactory.freePointer(heldValue); + }) : null; + + return { + create(pointer: UniffiHandle): MatrixDriverCallback { + const instance = Object.create(MatrixDriverCallbackImpl.prototype); + instance[pointerLiteralSymbol] = pointer; + instance[destructorGuardSymbol] = this.bless(pointer); + instance[uniffiTypeNameSymbol] = "MatrixDriverCallbackImpl"; + return instance; + }, + + + bless(p: UniffiHandle): UniffiGcObject { + const ptr = { + p, // make sure this object doesn't get optimized away. + markDestroyed: () => undefined, + }; + if (registry) { + registry.register(ptr, p, ptr); + } + return ptr; + }, + + unbless(ptr_: UniffiGcObject) { + if (registry) { + registry.unregister(ptr_); + } + }, + + pointer(obj_: MatrixDriverCallback): UniffiHandle { + if ((obj_ as any)[destructorGuardSymbol] === undefined) { + throw new UniffiInternalError.UnexpectedNullPointer(); + } + return (obj_ as any)[pointerLiteralSymbol]; + }, + + clonePointer(obj_: MatrixDriverCallback): UniffiHandle { + const pointer = this.pointer(obj_); + return uniffiCaller.rustCall( + /*caller:*/ (callStatus) => nativeModule().ubrn_uniffi_matrix_rtc_fn_clone_matrixdrivercallback(pointer, callStatus), + /*liftString:*/ FfiConverterString.lift + ); + }, + + freePointer(pointer: UniffiHandle): void { + uniffiCaller.rustCall( + /*caller:*/ (callStatus) => nativeModule().ubrn_uniffi_matrix_rtc_fn_free_matrixdrivercallback(pointer, callStatus), + /*liftString:*/ FfiConverterString.lift + ); + }, + + isConcreteType(obj_: any): obj_ is MatrixDriverCallback { + return obj_[destructorGuardSymbol] && obj_[uniffiTypeNameSymbol] === "MatrixDriverCallbackImpl"; + }, +}})(); +const FfiConverterTypeMatrixDriverCallback = new FfiConverterObjectWithCallbacks(uniffiTypeMatrixDriverCallbackImplObjectFactory); + +// Add a vtable for the callbacks that go in MatrixDriverCallback. + +// Put the implementation in a struct so we don't pollute the top-level namespace +const uniffiCallbackInterfaceMatrixDriverCallback: { vtable: any; register: () => void; } = { + // Create the VTable using a series of closures. + // ts automatically converts these into C callback functions. + vtable: { + send_sticky_event: ( + uniffiHandle: bigint, + roomId: Uint8Array, + eventType: Uint8Array, + contentJson: Uint8Array, + durationMs: bigint, + uniffiFutureCallback: UniffiForeignFutureCompleterustBuffer, + uniffiCallbackData: bigint) => { + const uniffiMakeCall = + async (signal: AbortSignal) + : Promise => { + const jsCallback = FfiConverterTypeMatrixDriverCallback.lift(uniffiHandle); + return await jsCallback.sendStickyEvent( + FfiConverterString.lift(roomId), + FfiConverterString.lift(eventType), + FfiConverterString.lift(contentJson), + FfiConverterUInt64.lift(durationMs), { signal } + ) + }; + const uniffiHandleSuccess = (returnValue: FfiSendEventResponse) => { + uniffiFutureCallback.call( + uniffiFutureCallback, + uniffiCallbackData, + /* UniffiForeignFutureResultRustBuffer */{ + return_value: FfiConverterTypeFfiSendEventResponse.lower(returnValue, nativeModule().rustbuffer_alloc), + call_status: uniffiCaller.createCallStatus() + } + ); + }; + const uniffiHandleError = (code: number, errorBuf: UniffiByteArray) => { + uniffiFutureCallback.call( + uniffiFutureCallback, + uniffiCallbackData, + /* UniffiForeignFutureResultRustBuffer */{ + return_value: /*empty*/ new Uint8Array(0), + // TODO create callstatus with error. + call_status: uniffiCaller.createErrorStatus(code, errorBuf), + } + ); + }; + const uniffiForeignFuture = uniffiTraitInterfaceCallAsyncWithError( + /*makeCall:*/ uniffiMakeCall, + /*handleSuccess:*/ uniffiHandleSuccess, + /*handleError:*/ uniffiHandleError, + /*isErrorType:*/ RtcError.instanceOf, + /*lowerError:*/ FfiConverterTypeRtcError.lower.bind(FfiConverterTypeRtcError), + /*lowerString:*/ FfiConverterString.lower.bind(FfiConverterString), + /*alloc:*/ nativeModule().rustbuffer_alloc, + ); + return uniffiForeignFuture; + }, + send_state_event: ( + uniffiHandle: bigint, + roomId: Uint8Array, + eventType: Uint8Array, + stateKey: Uint8Array, + contentJson: Uint8Array, + uniffiFutureCallback: UniffiForeignFutureCompleterustBuffer, + uniffiCallbackData: bigint) => { + const uniffiMakeCall = + async (signal: AbortSignal) + : Promise => { + const jsCallback = FfiConverterTypeMatrixDriverCallback.lift(uniffiHandle); + return await jsCallback.sendStateEvent( + FfiConverterString.lift(roomId), + FfiConverterString.lift(eventType), + FfiConverterString.lift(stateKey), + FfiConverterString.lift(contentJson), { signal } + ) + }; + const uniffiHandleSuccess = (returnValue: FfiSendEventResponse) => { + uniffiFutureCallback.call( + uniffiFutureCallback, + uniffiCallbackData, + /* UniffiForeignFutureResultRustBuffer */{ + return_value: FfiConverterTypeFfiSendEventResponse.lower(returnValue, nativeModule().rustbuffer_alloc), + call_status: uniffiCaller.createCallStatus() + } + ); + }; + const uniffiHandleError = (code: number, errorBuf: UniffiByteArray) => { + uniffiFutureCallback.call( + uniffiFutureCallback, + uniffiCallbackData, + /* UniffiForeignFutureResultRustBuffer */{ + return_value: /*empty*/ new Uint8Array(0), + // TODO create callstatus with error. + call_status: uniffiCaller.createErrorStatus(code, errorBuf), + } + ); + }; + const uniffiForeignFuture = uniffiTraitInterfaceCallAsyncWithError( + /*makeCall:*/ uniffiMakeCall, + /*handleSuccess:*/ uniffiHandleSuccess, + /*handleError:*/ uniffiHandleError, + /*isErrorType:*/ RtcError.instanceOf, + /*lowerError:*/ FfiConverterTypeRtcError.lower.bind(FfiConverterTypeRtcError), + /*lowerString:*/ FfiConverterString.lower.bind(FfiConverterString), + /*alloc:*/ nativeModule().rustbuffer_alloc, + ); + return uniffiForeignFuture; + }, + send_delayed_event: ( + uniffiHandle: bigint, + roomId: Uint8Array, + eventType: Uint8Array, + contentJson: Uint8Array, + delayMs: bigint, + stickyDurationMs: Uint8Array, + uniffiFutureCallback: UniffiForeignFutureCompleterustBuffer, + uniffiCallbackData: bigint) => { + const uniffiMakeCall = + async (signal: AbortSignal) + : Promise => { + const jsCallback = FfiConverterTypeMatrixDriverCallback.lift(uniffiHandle); + return await jsCallback.sendDelayedEvent( + FfiConverterString.lift(roomId), + FfiConverterString.lift(eventType), + FfiConverterString.lift(contentJson), + FfiConverterUInt64.lift(delayMs), + FfiConverterOptionalUInt64.lift(stickyDurationMs), { signal } + ) + }; + const uniffiHandleSuccess = (returnValue: string) => { + uniffiFutureCallback.call( + uniffiFutureCallback, + uniffiCallbackData, + /* UniffiForeignFutureResultRustBuffer */{ + return_value: FfiConverterString.lower(returnValue, nativeModule().rustbuffer_alloc), + call_status: uniffiCaller.createCallStatus() + } + ); + }; + const uniffiHandleError = (code: number, errorBuf: UniffiByteArray) => { + uniffiFutureCallback.call( + uniffiFutureCallback, + uniffiCallbackData, + /* UniffiForeignFutureResultRustBuffer */{ + return_value: /*empty*/ new Uint8Array(0), + // TODO create callstatus with error. + call_status: uniffiCaller.createErrorStatus(code, errorBuf), + } + ); + }; + const uniffiForeignFuture = uniffiTraitInterfaceCallAsyncWithError( + /*makeCall:*/ uniffiMakeCall, + /*handleSuccess:*/ uniffiHandleSuccess, + /*handleError:*/ uniffiHandleError, + /*isErrorType:*/ RtcError.instanceOf, + /*lowerError:*/ FfiConverterTypeRtcError.lower.bind(FfiConverterTypeRtcError), + /*lowerString:*/ FfiConverterString.lower.bind(FfiConverterString), + /*alloc:*/ nativeModule().rustbuffer_alloc, + ); + return uniffiForeignFuture; + }, + send_delayed_state_event: ( + uniffiHandle: bigint, + roomId: Uint8Array, + eventType: Uint8Array, + stateKey: Uint8Array, + contentJson: Uint8Array, + delayMs: bigint, + uniffiFutureCallback: UniffiForeignFutureCompleterustBuffer, + uniffiCallbackData: bigint) => { + const uniffiMakeCall = + async (signal: AbortSignal) + : Promise => { + const jsCallback = FfiConverterTypeMatrixDriverCallback.lift(uniffiHandle); + return await jsCallback.sendDelayedStateEvent( + FfiConverterString.lift(roomId), + FfiConverterString.lift(eventType), + FfiConverterString.lift(stateKey), + FfiConverterString.lift(contentJson), + FfiConverterUInt64.lift(delayMs), { signal } + ) + }; + const uniffiHandleSuccess = (returnValue: string) => { + uniffiFutureCallback.call( + uniffiFutureCallback, + uniffiCallbackData, + /* UniffiForeignFutureResultRustBuffer */{ + return_value: FfiConverterString.lower(returnValue, nativeModule().rustbuffer_alloc), + call_status: uniffiCaller.createCallStatus() + } + ); + }; + const uniffiHandleError = (code: number, errorBuf: UniffiByteArray) => { + uniffiFutureCallback.call( + uniffiFutureCallback, + uniffiCallbackData, + /* UniffiForeignFutureResultRustBuffer */{ + return_value: /*empty*/ new Uint8Array(0), + // TODO create callstatus with error. + call_status: uniffiCaller.createErrorStatus(code, errorBuf), + } + ); + }; + const uniffiForeignFuture = uniffiTraitInterfaceCallAsyncWithError( + /*makeCall:*/ uniffiMakeCall, + /*handleSuccess:*/ uniffiHandleSuccess, + /*handleError:*/ uniffiHandleError, + /*isErrorType:*/ RtcError.instanceOf, + /*lowerError:*/ FfiConverterTypeRtcError.lower.bind(FfiConverterTypeRtcError), + /*lowerString:*/ FfiConverterString.lower.bind(FfiConverterString), + /*alloc:*/ nativeModule().rustbuffer_alloc, + ); + return uniffiForeignFuture; + }, + restart_delayed_event: ( + uniffiHandle: bigint, + roomId: Uint8Array, + delayId: Uint8Array, + uniffiFutureCallback: UniffiForeignFutureCompletevoid, + uniffiCallbackData: bigint) => { + const uniffiMakeCall = + async (signal: AbortSignal) + : Promise => { + const jsCallback = FfiConverterTypeMatrixDriverCallback.lift(uniffiHandle); + return await jsCallback.restartDelayedEvent( + FfiConverterString.lift(roomId), + FfiConverterString.lift(delayId), { signal } + ) + }; + const uniffiHandleSuccess = (returnValue: void) => { + uniffiFutureCallback.call( + uniffiFutureCallback, + uniffiCallbackData, + /* UniffiForeignFutureResultVoid */{ + call_status: uniffiCaller.createCallStatus() + } + ); + }; + const uniffiHandleError = (code: number, errorBuf: UniffiByteArray) => { + uniffiFutureCallback.call( + uniffiFutureCallback, + uniffiCallbackData, + /* UniffiForeignFutureResultVoid */{ + // TODO create callstatus with error. + call_status: uniffiCaller.createErrorStatus(code, errorBuf), + } + ); + }; + const uniffiForeignFuture = uniffiTraitInterfaceCallAsyncWithError( + /*makeCall:*/ uniffiMakeCall, + /*handleSuccess:*/ uniffiHandleSuccess, + /*handleError:*/ uniffiHandleError, + /*isErrorType:*/ RtcError.instanceOf, + /*lowerError:*/ FfiConverterTypeRtcError.lower.bind(FfiConverterTypeRtcError), + /*lowerString:*/ FfiConverterString.lower.bind(FfiConverterString), + /*alloc:*/ nativeModule().rustbuffer_alloc, + ); + return uniffiForeignFuture; + }, + cancel_delayed_event: ( + uniffiHandle: bigint, + roomId: Uint8Array, + delayId: Uint8Array, + uniffiFutureCallback: UniffiForeignFutureCompletevoid, + uniffiCallbackData: bigint) => { + const uniffiMakeCall = + async (signal: AbortSignal) + : Promise => { + const jsCallback = FfiConverterTypeMatrixDriverCallback.lift(uniffiHandle); + return await jsCallback.cancelDelayedEvent( + FfiConverterString.lift(roomId), + FfiConverterString.lift(delayId), { signal } + ) + }; + const uniffiHandleSuccess = (returnValue: void) => { + uniffiFutureCallback.call( + uniffiFutureCallback, + uniffiCallbackData, + /* UniffiForeignFutureResultVoid */{ + call_status: uniffiCaller.createCallStatus() + } + ); + }; + const uniffiHandleError = (code: number, errorBuf: UniffiByteArray) => { + uniffiFutureCallback.call( + uniffiFutureCallback, + uniffiCallbackData, + /* UniffiForeignFutureResultVoid */{ + // TODO create callstatus with error. + call_status: uniffiCaller.createErrorStatus(code, errorBuf), + } + ); + }; + const uniffiForeignFuture = uniffiTraitInterfaceCallAsyncWithError( + /*makeCall:*/ uniffiMakeCall, + /*handleSuccess:*/ uniffiHandleSuccess, + /*handleError:*/ uniffiHandleError, + /*isErrorType:*/ RtcError.instanceOf, + /*lowerError:*/ FfiConverterTypeRtcError.lower.bind(FfiConverterTypeRtcError), + /*lowerString:*/ FfiConverterString.lower.bind(FfiConverterString), + /*alloc:*/ nativeModule().rustbuffer_alloc, + ); + return uniffiForeignFuture; + }, + delegate_livekit_delayed_leave: ( + uniffiHandle: bigint, + roomId: Uint8Array, + slotId: Uint8Array, + memberJson: Uint8Array, + delayId: Uint8Array, + livekitServiceUrl: Uint8Array, + delayMs: bigint, + uniffiFutureCallback: UniffiForeignFutureCompletevoid, + uniffiCallbackData: bigint) => { + const uniffiMakeCall = + async (signal: AbortSignal) + : Promise => { + const jsCallback = FfiConverterTypeMatrixDriverCallback.lift(uniffiHandle); + return await jsCallback.delegateLivekitDelayedLeave( + FfiConverterString.lift(roomId), + FfiConverterString.lift(slotId), + FfiConverterString.lift(memberJson), + FfiConverterString.lift(delayId), + FfiConverterOptionalString.lift(livekitServiceUrl), + FfiConverterUInt64.lift(delayMs), { signal } + ) + }; + const uniffiHandleSuccess = (returnValue: void) => { + uniffiFutureCallback.call( + uniffiFutureCallback, + uniffiCallbackData, + /* UniffiForeignFutureResultVoid */{ + call_status: uniffiCaller.createCallStatus() + } + ); + }; + const uniffiHandleError = (code: number, errorBuf: UniffiByteArray) => { + uniffiFutureCallback.call( + uniffiFutureCallback, + uniffiCallbackData, + /* UniffiForeignFutureResultVoid */{ + // TODO create callstatus with error. + call_status: uniffiCaller.createErrorStatus(code, errorBuf), + } + ); + }; + const uniffiForeignFuture = uniffiTraitInterfaceCallAsyncWithError( + /*makeCall:*/ uniffiMakeCall, + /*handleSuccess:*/ uniffiHandleSuccess, + /*handleError:*/ uniffiHandleError, + /*isErrorType:*/ RtcError.instanceOf, + /*lowerError:*/ FfiConverterTypeRtcError.lower.bind(FfiConverterTypeRtcError), + /*lowerString:*/ FfiConverterString.lower.bind(FfiConverterString), + /*alloc:*/ nativeModule().rustbuffer_alloc, + ); + return uniffiForeignFuture; + }, + send_to_device: ( + uniffiHandle: bigint, + recipients: Uint8Array, + eventType: Uint8Array, + contentJson: Uint8Array, + uniffiFutureCallback: UniffiForeignFutureCompleterustBuffer, + uniffiCallbackData: bigint) => { + const uniffiMakeCall = + async (signal: AbortSignal) + : Promise> => { + const jsCallback = FfiConverterTypeMatrixDriverCallback.lift(uniffiHandle); + return await jsCallback.sendToDevice( + FfiConverterSequenceTypeFfiToDeviceRecipient.lift(recipients), + FfiConverterString.lift(eventType), + FfiConverterString.lift(contentJson), { signal } + ) + }; + const uniffiHandleSuccess = (returnValue: Array) => { + uniffiFutureCallback.call( + uniffiFutureCallback, + uniffiCallbackData, + /* UniffiForeignFutureResultRustBuffer */{ + return_value: FfiConverterSequenceTypeFfiToDeviceDelivery.lower(returnValue, nativeModule().rustbuffer_alloc), + call_status: uniffiCaller.createCallStatus() + } + ); + }; + const uniffiHandleError = (code: number, errorBuf: UniffiByteArray) => { + uniffiFutureCallback.call( + uniffiFutureCallback, + uniffiCallbackData, + /* UniffiForeignFutureResultRustBuffer */{ + return_value: /*empty*/ new Uint8Array(0), + // TODO create callstatus with error. + call_status: uniffiCaller.createErrorStatus(code, errorBuf), + } + ); + }; + const uniffiForeignFuture = uniffiTraitInterfaceCallAsyncWithError( + /*makeCall:*/ uniffiMakeCall, + /*handleSuccess:*/ uniffiHandleSuccess, + /*handleError:*/ uniffiHandleError, + /*isErrorType:*/ RtcError.instanceOf, + /*lowerError:*/ FfiConverterTypeRtcError.lower.bind(FfiConverterTypeRtcError), + /*lowerString:*/ FfiConverterString.lower.bind(FfiConverterString), + /*alloc:*/ nativeModule().rustbuffer_alloc, + ); + return uniffiForeignFuture; + }, + get_rtc_transports: ( + uniffiHandle: bigint, + uniffiFutureCallback: UniffiForeignFutureCompleterustBuffer, + uniffiCallbackData: bigint) => { + const uniffiMakeCall = + async (signal: AbortSignal) + : Promise> => { + const jsCallback = FfiConverterTypeMatrixDriverCallback.lift(uniffiHandle); + return await jsCallback.getRtcTransports({ signal } + ) + }; + const uniffiHandleSuccess = (returnValue: Array) => { + uniffiFutureCallback.call( + uniffiFutureCallback, + uniffiCallbackData, + /* UniffiForeignFutureResultRustBuffer */{ + return_value: FfiConverterSequenceTypeFfiRtcTransport.lower(returnValue, nativeModule().rustbuffer_alloc), + call_status: uniffiCaller.createCallStatus() + } + ); + }; + const uniffiHandleError = (code: number, errorBuf: UniffiByteArray) => { + uniffiFutureCallback.call( + uniffiFutureCallback, + uniffiCallbackData, + /* UniffiForeignFutureResultRustBuffer */{ + return_value: /*empty*/ new Uint8Array(0), + // TODO create callstatus with error. + call_status: uniffiCaller.createErrorStatus(code, errorBuf), + } + ); + }; + const uniffiForeignFuture = uniffiTraitInterfaceCallAsyncWithError( + /*makeCall:*/ uniffiMakeCall, + /*handleSuccess:*/ uniffiHandleSuccess, + /*handleError:*/ uniffiHandleError, + /*isErrorType:*/ RtcError.instanceOf, + /*lowerError:*/ FfiConverterTypeRtcError.lower.bind(FfiConverterTypeRtcError), + /*lowerString:*/ FfiConverterString.lower.bind(FfiConverterString), + /*alloc:*/ nativeModule().rustbuffer_alloc, + ); + return uniffiForeignFuture; + }, + get_livekit_token: ( + uniffiHandle: bigint, + request: Uint8Array, + uniffiFutureCallback: UniffiForeignFutureCompleterustBuffer, + uniffiCallbackData: bigint) => { + const uniffiMakeCall = + async (signal: AbortSignal) + : Promise => { + const jsCallback = FfiConverterTypeMatrixDriverCallback.lift(uniffiHandle); + return await jsCallback.getLivekitToken( + FfiConverterTypeFfiLivekitTokenRequest.lift(request), { signal } + ) + }; + const uniffiHandleSuccess = (returnValue: FfiLivekitToken) => { + uniffiFutureCallback.call( + uniffiFutureCallback, + uniffiCallbackData, + /* UniffiForeignFutureResultRustBuffer */{ + return_value: FfiConverterTypeFfiLivekitToken.lower(returnValue, nativeModule().rustbuffer_alloc), + call_status: uniffiCaller.createCallStatus() + } + ); + }; + const uniffiHandleError = (code: number, errorBuf: UniffiByteArray) => { + uniffiFutureCallback.call( + uniffiFutureCallback, + uniffiCallbackData, + /* UniffiForeignFutureResultRustBuffer */{ + return_value: /*empty*/ new Uint8Array(0), + // TODO create callstatus with error. + call_status: uniffiCaller.createErrorStatus(code, errorBuf), + } + ); + }; + const uniffiForeignFuture = uniffiTraitInterfaceCallAsyncWithError( + /*makeCall:*/ uniffiMakeCall, + /*handleSuccess:*/ uniffiHandleSuccess, + /*handleError:*/ uniffiHandleError, + /*isErrorType:*/ RtcError.instanceOf, + /*lowerError:*/ FfiConverterTypeRtcError.lower.bind(FfiConverterTypeRtcError), + /*lowerString:*/ FfiConverterString.lower.bind(FfiConverterString), + /*alloc:*/ nativeModule().rustbuffer_alloc, + ); + return uniffiForeignFuture; + }, + read_events: ( + uniffiHandle: bigint, + eventType: Uint8Array, + stateKey: Uint8Array, + limit: number, + uniffiFutureCallback: UniffiForeignFutureCompleterustBuffer, + uniffiCallbackData: bigint) => { + const uniffiMakeCall = + async (signal: AbortSignal) + : Promise> => { + const jsCallback = FfiConverterTypeMatrixDriverCallback.lift(uniffiHandle); + return await jsCallback.readEvents( + FfiConverterString.lift(eventType), + FfiConverterOptionalString.lift(stateKey), + FfiConverterUInt32.lift(limit), { signal } + ) + }; + const uniffiHandleSuccess = (returnValue: Array) => { + uniffiFutureCallback.call( + uniffiFutureCallback, + uniffiCallbackData, + /* UniffiForeignFutureResultRustBuffer */{ + return_value: FfiConverterSequenceString.lower(returnValue, nativeModule().rustbuffer_alloc), + call_status: uniffiCaller.createCallStatus() + } + ); + }; + const uniffiHandleError = (code: number, errorBuf: UniffiByteArray) => { + uniffiFutureCallback.call( + uniffiFutureCallback, + uniffiCallbackData, + /* UniffiForeignFutureResultRustBuffer */{ + return_value: /*empty*/ new Uint8Array(0), + // TODO create callstatus with error. + call_status: uniffiCaller.createErrorStatus(code, errorBuf), + } + ); + }; + const uniffiForeignFuture = uniffiTraitInterfaceCallAsyncWithError( + /*makeCall:*/ uniffiMakeCall, + /*handleSuccess:*/ uniffiHandleSuccess, + /*handleError:*/ uniffiHandleError, + /*isErrorType:*/ RtcError.instanceOf, + /*lowerError:*/ FfiConverterTypeRtcError.lower.bind(FfiConverterTypeRtcError), + /*lowerString:*/ FfiConverterString.lower.bind(FfiConverterString), + /*alloc:*/ nativeModule().rustbuffer_alloc, + ); + return uniffiForeignFuture; + }, + read_state: ( + uniffiHandle: bigint, + eventType: Uint8Array, + stateKey: Uint8Array, + uniffiFutureCallback: UniffiForeignFutureCompleterustBuffer, + uniffiCallbackData: bigint) => { + const uniffiMakeCall = + async (signal: AbortSignal) + : Promise> => { + const jsCallback = FfiConverterTypeMatrixDriverCallback.lift(uniffiHandle); + return await jsCallback.readState( + FfiConverterString.lift(eventType), + FfiConverterOptionalString.lift(stateKey), { signal } + ) + }; + const uniffiHandleSuccess = (returnValue: Array) => { + uniffiFutureCallback.call( + uniffiFutureCallback, + uniffiCallbackData, + /* UniffiForeignFutureResultRustBuffer */{ + return_value: FfiConverterSequenceString.lower(returnValue, nativeModule().rustbuffer_alloc), + call_status: uniffiCaller.createCallStatus() + } + ); + }; + const uniffiHandleError = (code: number, errorBuf: UniffiByteArray) => { + uniffiFutureCallback.call( + uniffiFutureCallback, + uniffiCallbackData, + /* UniffiForeignFutureResultRustBuffer */{ + return_value: /*empty*/ new Uint8Array(0), + // TODO create callstatus with error. + call_status: uniffiCaller.createErrorStatus(code, errorBuf), + } + ); + }; + const uniffiForeignFuture = uniffiTraitInterfaceCallAsyncWithError( + /*makeCall:*/ uniffiMakeCall, + /*handleSuccess:*/ uniffiHandleSuccess, + /*handleError:*/ uniffiHandleError, + /*isErrorType:*/ RtcError.instanceOf, + /*lowerError:*/ FfiConverterTypeRtcError.lower.bind(FfiConverterTypeRtcError), + /*lowerString:*/ FfiConverterString.lower.bind(FfiConverterString), + /*alloc:*/ nativeModule().rustbuffer_alloc, + ); + return uniffiForeignFuture; + }, + subscribe_room_events: ( + uniffiHandle: bigint, + sink: bigint,) => { + const uniffiMakeCall = + () + : void => { + const jsCallback = FfiConverterTypeMatrixDriverCallback.lift(uniffiHandle); + return jsCallback.subscribeRoomEvents( + FfiConverterTypeRoomEventSink.lift(sink) + ) + }; + const uniffiResult = UniffiResult.ready(); + const uniffiHandleSuccess = (obj: any) => {}; + const uniffiHandleError = (code: number, errBuf: UniffiByteArray) => { + UniffiResult.writeError(uniffiResult, code, errBuf); + }; + uniffiTraitInterfaceCall( + /*makeCall:*/ uniffiMakeCall, + /*handleSuccess:*/ uniffiHandleSuccess, + /*handleError:*/ uniffiHandleError, + /*lowerString:*/ FfiConverterString.lower.bind(FfiConverterString), + /*alloc:*/ nativeModule().rustbuffer_alloc, + ) + return uniffiResult; + }, + subscribe_to_device_events: ( + uniffiHandle: bigint, + sink: bigint,) => { + const uniffiMakeCall = + () + : void => { + const jsCallback = FfiConverterTypeMatrixDriverCallback.lift(uniffiHandle); + return jsCallback.subscribeToDeviceEvents( + FfiConverterTypeToDeviceSink.lift(sink) + ) + }; + const uniffiResult = UniffiResult.ready(); + const uniffiHandleSuccess = (obj: any) => {}; + const uniffiHandleError = (code: number, errBuf: UniffiByteArray) => { + UniffiResult.writeError(uniffiResult, code, errBuf); + }; + uniffiTraitInterfaceCall( + /*makeCall:*/ uniffiMakeCall, + /*handleSuccess:*/ uniffiHandleSuccess, + /*handleError:*/ uniffiHandleError, + /*lowerString:*/ FfiConverterString.lower.bind(FfiConverterString), + /*alloc:*/ nativeModule().rustbuffer_alloc, + ) + return uniffiResult; + }, + subscribe_state_updates: ( + uniffiHandle: bigint, + sink: bigint,) => { + const uniffiMakeCall = + () + : void => { + const jsCallback = FfiConverterTypeMatrixDriverCallback.lift(uniffiHandle); + return jsCallback.subscribeStateUpdates( + FfiConverterTypeStateUpdateSink.lift(sink) + ) + }; + const uniffiResult = UniffiResult.ready(); + const uniffiHandleSuccess = (obj: any) => {}; + const uniffiHandleError = (code: number, errBuf: UniffiByteArray) => { + UniffiResult.writeError(uniffiResult, code, errBuf); + }; + uniffiTraitInterfaceCall( + /*makeCall:*/ uniffiMakeCall, + /*handleSuccess:*/ uniffiHandleSuccess, + /*handleError:*/ uniffiHandleError, + /*lowerString:*/ FfiConverterString.lower.bind(FfiConverterString), + /*alloc:*/ nativeModule().rustbuffer_alloc, + ) + return uniffiResult; + }, + is_homeserver_connected: ( + uniffiHandle: bigint,) => { + const uniffiMakeCall = + () + : boolean => { + const jsCallback = FfiConverterTypeMatrixDriverCallback.lift(uniffiHandle); + return jsCallback.isHomeserverConnected( + ) + }; + const uniffiResult = UniffiResult.ready(); + const uniffiHandleSuccess = (obj: any) => { + UniffiResult.writeSuccess(uniffiResult, FfiConverterBool.lower(obj, nativeModule().rustbuffer_alloc)); + }; + const uniffiHandleError = (code: number, errBuf: UniffiByteArray) => { + UniffiResult.writeError(uniffiResult, code, errBuf); + }; + uniffiTraitInterfaceCall( + /*makeCall:*/ uniffiMakeCall, + /*handleSuccess:*/ uniffiHandleSuccess, + /*handleError:*/ uniffiHandleError, + /*lowerString:*/ FfiConverterString.lower.bind(FfiConverterString), + /*alloc:*/ nativeModule().rustbuffer_alloc, + ) + return uniffiResult; + }, + subscribe_connectivity: ( + uniffiHandle: bigint, + sink: bigint,) => { + const uniffiMakeCall = + () + : void => { + const jsCallback = FfiConverterTypeMatrixDriverCallback.lift(uniffiHandle); + return jsCallback.subscribeConnectivity( + FfiConverterTypeConnectivitySink.lift(sink) + ) + }; + const uniffiResult = UniffiResult.ready(); + const uniffiHandleSuccess = (obj: any) => {}; + const uniffiHandleError = (code: number, errBuf: UniffiByteArray) => { + UniffiResult.writeError(uniffiResult, code, errBuf); + }; + uniffiTraitInterfaceCall( + /*makeCall:*/ uniffiMakeCall, + /*handleSuccess:*/ uniffiHandleSuccess, + /*handleError:*/ uniffiHandleError, + /*lowerString:*/ FfiConverterString.lower.bind(FfiConverterString), + /*alloc:*/ nativeModule().rustbuffer_alloc, + ) + return uniffiResult; + }, + uniffi_free: (uniffiHandle: UniffiHandle): void => { + // this will throw a stale handle error if the handle isn't found. + FfiConverterTypeMatrixDriverCallback.drop(uniffiHandle); + }, + uniffi_clone: (uniffiHandle: UniffiHandle): UniffiHandle => { + return FfiConverterTypeMatrixDriverCallback.clone(uniffiHandle); + } + }, + register: () => {nativeModule().ubrn_uniffi_matrix_rtc_fn_init_callback_vtable_matrixdrivercallback( + uniffiCallbackInterfaceMatrixDriverCallback.vtable + ); + }, +}; + +// FfiConverter for bigint | undefined +const FfiConverterOptionalUInt64 = new FfiConverterOptional(FfiConverterUInt64); + +// FfiConverter for Array +const FfiConverterSequenceString = new FfiConverterArray(FfiConverterString); + +// FfiConverter for string | undefined +const FfiConverterOptionalString = new FfiConverterOptional(FfiConverterString); + +// FfiConverter for Array +const FfiConverterSequenceTypeFfiRtcTransport = new FfiConverterArray(FfiConverterTypeFfiRtcTransport); + +// FfiConverter for Array +const FfiConverterSequenceTypeFfiMember = new FfiConverterArray(FfiConverterTypeFfiMember); + +// FfiConverter for FfiKeyRejection | undefined +const FfiConverterOptionalTypeFfiKeyRejection = new FfiConverterOptional(FfiConverterTypeFfiKeyRejection); + +// FfiConverter for FfiMediaKeyState | undefined +const FfiConverterOptionalTypeFfiMediaKeyState = new FfiConverterOptional(FfiConverterTypeFfiMediaKeyState); + +// FfiConverter for boolean | undefined +const FfiConverterOptionalBoolean = new FfiConverterOptional(FfiConverterBool); + +// FfiConverter for Array +const FfiConverterSequenceTypeFfiSessionRead = new FfiConverterArray(FfiConverterTypeFfiSessionRead); + +// FfiConverter for Array +const FfiConverterSequenceTypeFfiExcludedCandidate = new FfiConverterArray(FfiConverterTypeFfiExcludedCandidate); + +// FfiConverter for Array +const FfiConverterSequenceTypeFfiImpairment = new FfiConverterArray(FfiConverterTypeFfiImpairment); + +// FfiConverter for FfiDelayedLeaveOutcome | undefined +const FfiConverterOptionalTypeFfiDelayedLeaveOutcome = new FfiConverterOptional(FfiConverterTypeFfiDelayedLeaveOutcome); + +// FfiConverter for Array +const FfiConverterSequenceTypeFfiConnectionWithMembers = new FfiConverterArray(FfiConverterTypeFfiConnectionWithMembers); + +// FfiConverter for Array +const FfiConverterSequenceTypeFfiConnectionProblem = new FfiConverterArray(FfiConverterTypeFfiConnectionProblem); + +// FfiConverter for Array +const FfiConverterSequenceTypeFfiMediaKey = new FfiConverterArray(FfiConverterTypeFfiMediaKey); + +// FfiConverter for Array +const FfiConverterSequenceTypeFfiMembership = new FfiConverterArray(FfiConverterTypeFfiMembership); + +// FfiConverter for FfiMembership | undefined +const FfiConverterOptionalTypeFfiMembership = new FfiConverterOptional(FfiConverterTypeFfiMembership); + +// FfiConverter for Array +const FfiConverterSequenceTypeFfiToDeviceRecipient = new FfiConverterArray(FfiConverterTypeFfiToDeviceRecipient); + +// FfiConverter for Array +const FfiConverterSequenceTypeFfiToDeviceDelivery = new FfiConverterArray(FfiConverterTypeFfiToDeviceDelivery); + +// FfiConverter for Array +const FfiConverterSequenceTypeFfiSessionSnapshot = new FfiConverterArray(FfiConverterTypeFfiSessionSnapshot); + + +/** + * This should be called before anything else. + * + * It is likely that this is being done for you by the library's `index.ts`. + * + * It checks versions of uniffi between when the Rust scaffolding was generated + * and when the bindings were generated. + * + * It also initializes the machinery to enable Rust to talk back to Javascript. + */ +function uniffiEnsureInitialized() { + // Get the bindings contract version from our ComponentInterface + const bindingsContractVersion = 30; + // Get the scaffolding contract version by calling the into the dylib + const scaffoldingContractVersion = nativeModule().ubrn_ffi_matrix_rtc_uniffi_contract_version(); + if (bindingsContractVersion !== scaffoldingContractVersion) { + throw new UniffiInternalError.ContractVersionMismatch(scaffoldingContractVersion, bindingsContractVersion); + } + if (nativeModule().ubrn_uniffi_matrix_rtc_checksum_func_compute_sessions_from_events() !== 27010) { + throw new UniffiInternalError.ApiChecksumMismatch("uniffi_matrix_rtc_checksum_func_compute_sessions_from_events"); + } + if (nativeModule().ubrn_uniffi_matrix_rtc_checksum_func_impairment_severity() !== 9139) { + throw new UniffiInternalError.ApiChecksumMismatch("uniffi_matrix_rtc_checksum_func_impairment_severity"); + } + if (nativeModule().ubrn_uniffi_matrix_rtc_checksum_method_connectionslistener_on_connections_change() !== 24219) { + throw new UniffiInternalError.ApiChecksumMismatch("uniffi_matrix_rtc_checksum_method_connectionslistener_on_connections_change"); + } + if (nativeModule().ubrn_uniffi_matrix_rtc_checksum_method_connectivitysink_emit() !== 45059) { + throw new UniffiInternalError.ApiChecksumMismatch("uniffi_matrix_rtc_checksum_method_connectivitysink_emit"); + } + if (nativeModule().ubrn_uniffi_matrix_rtc_checksum_constructor_ffimatrixdriver_new() !== 16380) { + throw new UniffiInternalError.ApiChecksumMismatch("uniffi_matrix_rtc_checksum_constructor_ffimatrixdriver_new"); + } + if (nativeModule().ubrn_uniffi_matrix_rtc_checksum_constructor_ffiparticipationmanager_new() !== 2422) { + throw new UniffiInternalError.ApiChecksumMismatch("uniffi_matrix_rtc_checksum_constructor_ffiparticipationmanager_new"); + } + if (nativeModule().ubrn_uniffi_matrix_rtc_checksum_method_ffiparticipationmanager_close_slot() !== 63268) { + throw new UniffiInternalError.ApiChecksumMismatch("uniffi_matrix_rtc_checksum_method_ffiparticipationmanager_close_slot"); + } + if (nativeModule().ubrn_uniffi_matrix_rtc_checksum_method_ffiparticipationmanager_connection_problems() !== 17464) { + throw new UniffiInternalError.ApiChecksumMismatch("uniffi_matrix_rtc_checksum_method_ffiparticipationmanager_connection_problems"); + } + if (nativeModule().ubrn_uniffi_matrix_rtc_checksum_method_ffiparticipationmanager_connections() !== 38871) { + throw new UniffiInternalError.ApiChecksumMismatch("uniffi_matrix_rtc_checksum_method_ffiparticipationmanager_connections"); + } + if (nativeModule().ubrn_uniffi_matrix_rtc_checksum_method_ffiparticipationmanager_debug_snapshot() !== 11860) { + throw new UniffiInternalError.ApiChecksumMismatch("uniffi_matrix_rtc_checksum_method_ffiparticipationmanager_debug_snapshot"); + } + if (nativeModule().ubrn_uniffi_matrix_rtc_checksum_method_ffiparticipationmanager_is_homeserver_connected() !== 218) { + throw new UniffiInternalError.ApiChecksumMismatch("uniffi_matrix_rtc_checksum_method_ffiparticipationmanager_is_homeserver_connected"); + } + if (nativeModule().ubrn_uniffi_matrix_rtc_checksum_method_ffiparticipationmanager_join() !== 18117) { + throw new UniffiInternalError.ApiChecksumMismatch("uniffi_matrix_rtc_checksum_method_ffiparticipationmanager_join"); + } + if (nativeModule().ubrn_uniffi_matrix_rtc_checksum_method_ffiparticipationmanager_key_map() !== 32581) { + throw new UniffiInternalError.ApiChecksumMismatch("uniffi_matrix_rtc_checksum_method_ffiparticipationmanager_key_map"); + } + if (nativeModule().ubrn_uniffi_matrix_rtc_checksum_method_ffiparticipationmanager_leave() !== 35402) { + throw new UniffiInternalError.ApiChecksumMismatch("uniffi_matrix_rtc_checksum_method_ffiparticipationmanager_leave"); + } + if (nativeModule().ubrn_uniffi_matrix_rtc_checksum_method_ffiparticipationmanager_memberships() !== 15145) { + throw new UniffiInternalError.ApiChecksumMismatch("uniffi_matrix_rtc_checksum_method_ffiparticipationmanager_memberships"); + } + if (nativeModule().ubrn_uniffi_matrix_rtc_checksum_method_ffiparticipationmanager_open_slot() !== 28952) { + throw new UniffiInternalError.ApiChecksumMismatch("uniffi_matrix_rtc_checksum_method_ffiparticipationmanager_open_slot"); + } + if (nativeModule().ubrn_uniffi_matrix_rtc_checksum_method_ffiparticipationmanager_own_member_id() !== 453) { + throw new UniffiInternalError.ApiChecksumMismatch("uniffi_matrix_rtc_checksum_method_ffiparticipationmanager_own_member_id"); + } + if (nativeModule().ubrn_uniffi_matrix_rtc_checksum_method_ffiparticipationmanager_own_membership() !== 25006) { + throw new UniffiInternalError.ApiChecksumMismatch("uniffi_matrix_rtc_checksum_method_ffiparticipationmanager_own_membership"); + } + if (nativeModule().ubrn_uniffi_matrix_rtc_checksum_method_ffiparticipationmanager_own_transport_identity() !== 34101) { + throw new UniffiInternalError.ApiChecksumMismatch("uniffi_matrix_rtc_checksum_method_ffiparticipationmanager_own_transport_identity"); + } + if (nativeModule().ubrn_uniffi_matrix_rtc_checksum_method_ffiparticipationmanager_session() !== 13049) { + throw new UniffiInternalError.ApiChecksumMismatch("uniffi_matrix_rtc_checksum_method_ffiparticipationmanager_session"); + } + if (nativeModule().ubrn_uniffi_matrix_rtc_checksum_method_ffiparticipationmanager_set_connections_listener() !== 33842) { + throw new UniffiInternalError.ApiChecksumMismatch("uniffi_matrix_rtc_checksum_method_ffiparticipationmanager_set_connections_listener"); + } + if (nativeModule().ubrn_uniffi_matrix_rtc_checksum_method_ffiparticipationmanager_set_key_map_listener() !== 53147) { + throw new UniffiInternalError.ApiChecksumMismatch("uniffi_matrix_rtc_checksum_method_ffiparticipationmanager_set_key_map_listener"); + } + if (nativeModule().ubrn_uniffi_matrix_rtc_checksum_method_ffiparticipationmanager_set_key_rejected_listener() !== 1468) { + throw new UniffiInternalError.ApiChecksumMismatch("uniffi_matrix_rtc_checksum_method_ffiparticipationmanager_set_key_rejected_listener"); + } + if (nativeModule().ubrn_uniffi_matrix_rtc_checksum_method_ffiparticipationmanager_set_memberships_listener() !== 46727) { + throw new UniffiInternalError.ApiChecksumMismatch("uniffi_matrix_rtc_checksum_method_ffiparticipationmanager_set_memberships_listener"); + } + if (nativeModule().ubrn_uniffi_matrix_rtc_checksum_method_ffiparticipationmanager_set_status_listener() !== 8439) { + throw new UniffiInternalError.ApiChecksumMismatch("uniffi_matrix_rtc_checksum_method_ffiparticipationmanager_set_status_listener"); + } + if (nativeModule().ubrn_uniffi_matrix_rtc_checksum_method_ffiparticipationmanager_status() !== 23619) { + throw new UniffiInternalError.ApiChecksumMismatch("uniffi_matrix_rtc_checksum_method_ffiparticipationmanager_status"); + } + if (nativeModule().ubrn_uniffi_matrix_rtc_checksum_method_ffiparticipationmanager_update_application() !== 28805) { + throw new UniffiInternalError.ApiChecksumMismatch("uniffi_matrix_rtc_checksum_method_ffiparticipationmanager_update_application"); + } + if (nativeModule().ubrn_uniffi_matrix_rtc_checksum_method_keymaplistener_on_key_map_change() !== 2308) { + throw new UniffiInternalError.ApiChecksumMismatch("uniffi_matrix_rtc_checksum_method_keymaplistener_on_key_map_change"); + } + if (nativeModule().ubrn_uniffi_matrix_rtc_checksum_method_keyrejectedlistener_on_key_rejected() !== 53044) { + throw new UniffiInternalError.ApiChecksumMismatch("uniffi_matrix_rtc_checksum_method_keyrejectedlistener_on_key_rejected"); + } + if (nativeModule().ubrn_uniffi_matrix_rtc_checksum_method_matrixdrivercallback_send_sticky_event() !== 39725) { + throw new UniffiInternalError.ApiChecksumMismatch("uniffi_matrix_rtc_checksum_method_matrixdrivercallback_send_sticky_event"); + } + if (nativeModule().ubrn_uniffi_matrix_rtc_checksum_method_matrixdrivercallback_send_state_event() !== 11746) { + throw new UniffiInternalError.ApiChecksumMismatch("uniffi_matrix_rtc_checksum_method_matrixdrivercallback_send_state_event"); + } + if (nativeModule().ubrn_uniffi_matrix_rtc_checksum_method_matrixdrivercallback_send_delayed_event() !== 9018) { + throw new UniffiInternalError.ApiChecksumMismatch("uniffi_matrix_rtc_checksum_method_matrixdrivercallback_send_delayed_event"); + } + if (nativeModule().ubrn_uniffi_matrix_rtc_checksum_method_matrixdrivercallback_send_delayed_state_event() !== 29945) { + throw new UniffiInternalError.ApiChecksumMismatch("uniffi_matrix_rtc_checksum_method_matrixdrivercallback_send_delayed_state_event"); + } + if (nativeModule().ubrn_uniffi_matrix_rtc_checksum_method_matrixdrivercallback_restart_delayed_event() !== 2361) { + throw new UniffiInternalError.ApiChecksumMismatch("uniffi_matrix_rtc_checksum_method_matrixdrivercallback_restart_delayed_event"); + } + if (nativeModule().ubrn_uniffi_matrix_rtc_checksum_method_matrixdrivercallback_cancel_delayed_event() !== 48021) { + throw new UniffiInternalError.ApiChecksumMismatch("uniffi_matrix_rtc_checksum_method_matrixdrivercallback_cancel_delayed_event"); + } + if (nativeModule().ubrn_uniffi_matrix_rtc_checksum_method_matrixdrivercallback_delegate_livekit_delayed_leave() !== 31950) { + throw new UniffiInternalError.ApiChecksumMismatch("uniffi_matrix_rtc_checksum_method_matrixdrivercallback_delegate_livekit_delayed_leave"); + } + if (nativeModule().ubrn_uniffi_matrix_rtc_checksum_method_matrixdrivercallback_send_to_device() !== 29274) { + throw new UniffiInternalError.ApiChecksumMismatch("uniffi_matrix_rtc_checksum_method_matrixdrivercallback_send_to_device"); + } + if (nativeModule().ubrn_uniffi_matrix_rtc_checksum_method_matrixdrivercallback_get_rtc_transports() !== 55674) { + throw new UniffiInternalError.ApiChecksumMismatch("uniffi_matrix_rtc_checksum_method_matrixdrivercallback_get_rtc_transports"); + } + if (nativeModule().ubrn_uniffi_matrix_rtc_checksum_method_matrixdrivercallback_get_livekit_token() !== 36238) { + throw new UniffiInternalError.ApiChecksumMismatch("uniffi_matrix_rtc_checksum_method_matrixdrivercallback_get_livekit_token"); + } + if (nativeModule().ubrn_uniffi_matrix_rtc_checksum_method_matrixdrivercallback_read_events() !== 18104) { + throw new UniffiInternalError.ApiChecksumMismatch("uniffi_matrix_rtc_checksum_method_matrixdrivercallback_read_events"); + } + if (nativeModule().ubrn_uniffi_matrix_rtc_checksum_method_matrixdrivercallback_read_state() !== 58428) { + throw new UniffiInternalError.ApiChecksumMismatch("uniffi_matrix_rtc_checksum_method_matrixdrivercallback_read_state"); + } + if (nativeModule().ubrn_uniffi_matrix_rtc_checksum_method_matrixdrivercallback_subscribe_room_events() !== 31129) { + throw new UniffiInternalError.ApiChecksumMismatch("uniffi_matrix_rtc_checksum_method_matrixdrivercallback_subscribe_room_events"); + } + if (nativeModule().ubrn_uniffi_matrix_rtc_checksum_method_matrixdrivercallback_subscribe_to_device_events() !== 55587) { + throw new UniffiInternalError.ApiChecksumMismatch("uniffi_matrix_rtc_checksum_method_matrixdrivercallback_subscribe_to_device_events"); + } + if (nativeModule().ubrn_uniffi_matrix_rtc_checksum_method_matrixdrivercallback_subscribe_state_updates() !== 53493) { + throw new UniffiInternalError.ApiChecksumMismatch("uniffi_matrix_rtc_checksum_method_matrixdrivercallback_subscribe_state_updates"); + } + if (nativeModule().ubrn_uniffi_matrix_rtc_checksum_method_matrixdrivercallback_is_homeserver_connected() !== 28631) { + throw new UniffiInternalError.ApiChecksumMismatch("uniffi_matrix_rtc_checksum_method_matrixdrivercallback_is_homeserver_connected"); + } + if (nativeModule().ubrn_uniffi_matrix_rtc_checksum_method_matrixdrivercallback_subscribe_connectivity() !== 46098) { + throw new UniffiInternalError.ApiChecksumMismatch("uniffi_matrix_rtc_checksum_method_matrixdrivercallback_subscribe_connectivity"); + } + if (nativeModule().ubrn_uniffi_matrix_rtc_checksum_method_membershipslistener_on_memberships_change() !== 29319) { + throw new UniffiInternalError.ApiChecksumMismatch("uniffi_matrix_rtc_checksum_method_membershipslistener_on_memberships_change"); + } + if (nativeModule().ubrn_uniffi_matrix_rtc_checksum_method_roomeventsink_emit() !== 34604) { + throw new UniffiInternalError.ApiChecksumMismatch("uniffi_matrix_rtc_checksum_method_roomeventsink_emit"); + } + if (nativeModule().ubrn_uniffi_matrix_rtc_checksum_method_stateupdatesink_emit() !== 7988) { + throw new UniffiInternalError.ApiChecksumMismatch("uniffi_matrix_rtc_checksum_method_stateupdatesink_emit"); + } + if (nativeModule().ubrn_uniffi_matrix_rtc_checksum_method_statuslistener_on_status_change() !== 45246) { + throw new UniffiInternalError.ApiChecksumMismatch("uniffi_matrix_rtc_checksum_method_statuslistener_on_status_change"); + } + if (nativeModule().ubrn_uniffi_matrix_rtc_checksum_method_todevicesink_emit() !== 57061) { + throw new UniffiInternalError.ApiChecksumMismatch("uniffi_matrix_rtc_checksum_method_todevicesink_emit"); + } + + uniffiCallbackInterfaceConnectionsListener.register(); + uniffiCallbackInterfaceKeyMapListener.register(); + uniffiCallbackInterfaceKeyRejectedListener.register(); + uniffiCallbackInterfaceMembershipsListener.register(); + uniffiCallbackInterfaceStatusListener.register(); + uniffiCallbackInterfaceMatrixDriverCallback.register(); + } + +export default Object.freeze({ + initialize: uniffiEnsureInitialized, + converters: { + FfiConverterTypeConnectionsListener, + FfiConverterTypeConnectivitySink, + FfiConverterTypeFfiComponent, + FfiConverterTypeFfiConnectionData, + FfiConverterTypeFfiConnectionProblem, + FfiConverterTypeFfiConnectionProblemKind, + FfiConverterTypeFfiConnectionWithMembers, + FfiConverterTypeFfiDelayedLeaveOutcome, + FfiConverterTypeFfiDeviceAttribution, + FfiConverterTypeFfiDisconnectCause, + FfiConverterTypeFfiElementCallCompat, + FfiConverterTypeFfiEncryptionStatus, + FfiConverterTypeFfiEventOrigin, + FfiConverterTypeFfiExcludedCandidate, + FfiConverterTypeFfiImpairment, + FfiConverterTypeFfiJoinError, + FfiConverterTypeFfiJoinExclusionReason, + FfiConverterTypeFfiJoinParams, + FfiConverterTypeFfiJoinProgress, + FfiConverterTypeFfiKeepAlive, + FfiConverterTypeFfiKeyRejection, + FfiConverterTypeFfiLivekitToken, + FfiConverterTypeFfiLivekitTokenRequest, + FfiConverterTypeFfiMatrixDriver, + FfiConverterTypeFfiMediaKey, + FfiConverterTypeFfiMediaKeyState, + FfiConverterTypeFfiMember, + FfiConverterTypeFfiMembership, + FfiConverterTypeFfiMembershipPublication, + FfiConverterTypeFfiMembershipState, + FfiConverterTypeFfiParticipationConfig, + FfiConverterTypeFfiParticipationManager, + FfiConverterTypeFfiRosterPresence, + FfiConverterTypeFfiRtcTransport, + FfiConverterTypeFfiSendEventResponse, + FfiConverterTypeFfiSessionRead, + FfiConverterTypeFfiSessionSnapshot, + FfiConverterTypeFfiSeverity, + FfiConverterTypeFfiStatus, + FfiConverterTypeFfiToDeviceDelivery, + FfiConverterTypeFfiToDeviceRecipient, + FfiConverterTypeFfiTransportIntent, + FfiConverterTypeKeyMapListener, + FfiConverterTypeKeyRejectedListener, + FfiConverterTypeMatrixDriverCallback, + FfiConverterTypeMembershipsListener, + FfiConverterTypeRoomEventSink, + FfiConverterTypeRtcError, + FfiConverterTypeStateUpdateSink, + FfiConverterTypeStatusListener, + FfiConverterTypeToDeviceSink, + } +}); \ No newline at end of file diff --git a/src/matrix-rtc-sdk/generated/wasm-bindgen/index.d.ts b/src/matrix-rtc-sdk/generated/wasm-bindgen/index.d.ts new file mode 100644 index 000000000..204a74eea --- /dev/null +++ b/src/matrix-rtc-sdk/generated/wasm-bindgen/index.d.ts @@ -0,0 +1,30 @@ +/* +Copyright 2026 Element Creations Ltd. + +SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial +Please see LICENSE in the repository root for full details. +*/ + +// Hand-written declaration for the wasm-bindgen glue next to it, which ubrn +// emits as plain JavaScript. Only the loading entry points are declared; the +// exported `ubrn_*` FFI functions are reached through matrix_rtc.ts alone. +// Kept out of the sync script's way: it is not generated. + +/** What wasm-bindgen's loader accepts as the module to instantiate. */ +export type InitInput = + | RequestInfo + | URL + | Response + | BufferSource + | WebAssembly.Module; + +export default function initAsync( + moduleOrPath?: + | { module_or_path?: InitInput | Promise } + | InitInput + | Promise, +): Promise; + +export function initSync( + module: { module: BufferSource | WebAssembly.Module } | BufferSource | WebAssembly.Module, +): unknown; diff --git a/src/matrix-rtc-sdk/generated/wasm-bindgen/index.js b/src/matrix-rtc-sdk/generated/wasm-bindgen/index.js new file mode 100644 index 000000000..3692c76d9 --- /dev/null +++ b/src/matrix-rtc-sdk/generated/wasm-bindgen/index.js @@ -0,0 +1,3049 @@ +let wasm; + +let cachedUint8ArrayMemory0 = null; + +function getUint8ArrayMemory0() { + if (cachedUint8ArrayMemory0 === null || cachedUint8ArrayMemory0.byteLength === 0) { + cachedUint8ArrayMemory0 = new Uint8Array(wasm.memory.buffer); + } + return cachedUint8ArrayMemory0; +} + +function getArrayU8FromWasm0(ptr, len) { + ptr = ptr >>> 0; + return getUint8ArrayMemory0().subarray(ptr / 1, ptr / 1 + len); +} + +function addToExternrefTable0(obj) { + const idx = wasm.__externref_table_alloc(); + wasm.__wbindgen_export_3.set(idx, obj); + return idx; +} + +function handleError(f, args) { + try { + return f.apply(this, args); + } catch (e) { + const idx = addToExternrefTable0(e); + wasm.__wbindgen_exn_store(idx); + } +} + +function _assertClass(instance, klass) { + if (!(instance instanceof klass)) { + throw new Error(`expected instance of ${klass.name}`); + } +} + +let WASM_VECTOR_LEN = 0; + +function passArray8ToWasm0(arg, malloc) { + const ptr = malloc(arg.length * 1, 1) >>> 0; + getUint8ArrayMemory0().set(arg, ptr / 1); + WASM_VECTOR_LEN = arg.length; + return ptr; +} + +function isLikeNone(x) { + return x === undefined || x === null; +} + +let cachedDataViewMemory0 = null; + +function getDataViewMemory0() { + if (cachedDataViewMemory0 === null || cachedDataViewMemory0.buffer.detached === true || (cachedDataViewMemory0.buffer.detached === undefined && cachedDataViewMemory0.buffer !== wasm.memory.buffer)) { + cachedDataViewMemory0 = new DataView(wasm.memory.buffer); + } + return cachedDataViewMemory0; +} + +const cachedTextDecoder = (typeof TextDecoder !== 'undefined' ? new TextDecoder('utf-8', { ignoreBOM: true, fatal: true }) : { decode: () => { throw Error('TextDecoder not available') } } ); + +if (typeof TextDecoder !== 'undefined') { cachedTextDecoder.decode(); }; + +function getStringFromWasm0(ptr, len) { + ptr = ptr >>> 0; + return cachedTextDecoder.decode(getUint8ArrayMemory0().subarray(ptr, ptr + len)); +} + +const CLOSURE_DTORS = (typeof FinalizationRegistry === 'undefined') + ? { register: () => {}, unregister: () => {} } + : new FinalizationRegistry(state => { + wasm.__wbindgen_export_5.get(state.dtor)(state.a, state.b) +}); + +function makeMutClosure(arg0, arg1, dtor, f) { + const state = { a: arg0, b: arg1, cnt: 1, dtor }; + const real = (...args) => { + // First up with a closure we increment the internal reference + // count. This ensures that the Rust closure environment won't + // be deallocated while we're invoking it. + state.cnt++; + const a = state.a; + state.a = 0; + try { + return f(a, state.b, ...args); + } finally { + if (--state.cnt === 0) { + wasm.__wbindgen_export_5.get(state.dtor)(a, state.b); + CLOSURE_DTORS.unregister(state); + } else { + state.a = a; + } + } + }; + real.original = state; + CLOSURE_DTORS.register(real, state, state); + return real; +} +/** + * @param {bigint} handle + * @param {RustCallStatus} f_status_ + * @returns {bigint} + */ +export function ubrn_uniffi_matrix_rtc_fn_clone_connectionslistener(handle, f_status_) { + _assertClass(f_status_, RustCallStatus); + const ret = wasm.ubrn_uniffi_matrix_rtc_fn_clone_connectionslistener(handle, f_status_.__wbg_ptr); + return BigInt.asUintN(64, ret); +} + +/** + * @param {bigint} ptr + * @param {RustCallStatus} f_status_ + * @returns {Uint8Array} + */ +export function ubrn_uniffi_matrix_rtc_fn_method_ffiparticipationmanager_memberships(ptr, f_status_) { + _assertClass(f_status_, RustCallStatus); + const ret = wasm.ubrn_uniffi_matrix_rtc_fn_method_ffiparticipationmanager_memberships(ptr, f_status_.__wbg_ptr); + var v1 = getArrayU8FromWasm0(ret[0], ret[1]).slice(); + wasm.__wbindgen_free(ret[0], ret[1] * 1, 1); + return v1; +} + +/** + * @param {bigint} ptr + * @param {Uint8Array} application_type + * @param {number} encrypted + * @returns {bigint} + */ +export function ubrn_uniffi_matrix_rtc_fn_method_ffiparticipationmanager_open_slot(ptr, application_type, encrypted) { + const ptr0 = passArray8ToWasm0(application_type, wasm.__wbindgen_malloc); + const len0 = WASM_VECTOR_LEN; + const ret = wasm.ubrn_uniffi_matrix_rtc_fn_method_ffiparticipationmanager_open_slot(ptr, ptr0, len0, encrypted); + return BigInt.asUintN(64, ret); +} + +/** + * @param {bigint} ptr + * @param {RustCallStatus} f_status_ + * @returns {Uint8Array} + */ +export function ubrn_uniffi_matrix_rtc_fn_method_ffiparticipationmanager_own_member_id(ptr, f_status_) { + _assertClass(f_status_, RustCallStatus); + const ret = wasm.ubrn_uniffi_matrix_rtc_fn_method_ffiparticipationmanager_own_member_id(ptr, f_status_.__wbg_ptr); + var v1 = getArrayU8FromWasm0(ret[0], ret[1]).slice(); + wasm.__wbindgen_free(ret[0], ret[1] * 1, 1); + return v1; +} + +/** + * @param {bigint} ptr + * @param {Uint8Array} intent + * @returns {bigint} + */ +export function ubrn_uniffi_matrix_rtc_fn_method_ffiparticipationmanager_update_application(ptr, intent) { + const ptr0 = passArray8ToWasm0(intent, wasm.__wbindgen_malloc); + const len0 = WASM_VECTOR_LEN; + const ret = wasm.ubrn_uniffi_matrix_rtc_fn_method_ffiparticipationmanager_update_application(ptr, ptr0, len0); + return BigInt.asUintN(64, ret); +} + +/** + * @param {bigint} handle + * @param {RustCallStatus} f_status_ + * @returns {bigint} + */ +export function ubrn_uniffi_matrix_rtc_fn_clone_keymaplistener(handle, f_status_) { + _assertClass(f_status_, RustCallStatus); + const ret = wasm.ubrn_uniffi_matrix_rtc_fn_clone_keymaplistener(handle, f_status_.__wbg_ptr); + return BigInt.asUintN(64, ret); +} + +/** + * @param {bigint} handle + * @param {RustCallStatus} f_status_ + */ +export function ubrn_uniffi_matrix_rtc_fn_free_keymaplistener(handle, f_status_) { + _assertClass(f_status_, RustCallStatus); + wasm.ubrn_uniffi_matrix_rtc_fn_free_keymaplistener(handle, f_status_.__wbg_ptr); +} + +/** + * @param {any} vtable + */ +export function ubrn_uniffi_matrix_rtc_fn_init_callback_vtable_keymaplistener(vtable) { + wasm.ubrn_uniffi_matrix_rtc_fn_init_callback_vtable_keymaplistener(vtable); +} + +/** + * @param {bigint} ptr + * @param {Uint8Array} key_map + * @param {Uint8Array} change + * @param {RustCallStatus} f_status_ + */ +export function ubrn_uniffi_matrix_rtc_fn_method_keymaplistener_on_key_map_change(ptr, key_map, change, f_status_) { + const ptr0 = passArray8ToWasm0(key_map, wasm.__wbindgen_malloc); + const len0 = WASM_VECTOR_LEN; + const ptr1 = passArray8ToWasm0(change, wasm.__wbindgen_malloc); + const len1 = WASM_VECTOR_LEN; + _assertClass(f_status_, RustCallStatus); + wasm.ubrn_uniffi_matrix_rtc_fn_method_keymaplistener_on_key_map_change(ptr, ptr0, len0, ptr1, len1, f_status_.__wbg_ptr); +} + +/** + * @param {bigint} handle + * @param {RustCallStatus} f_status_ + * @returns {bigint} + */ +export function ubrn_uniffi_matrix_rtc_fn_clone_keyrejectedlistener(handle, f_status_) { + _assertClass(f_status_, RustCallStatus); + const ret = wasm.ubrn_uniffi_matrix_rtc_fn_clone_keyrejectedlistener(handle, f_status_.__wbg_ptr); + return BigInt.asUintN(64, ret); +} + +/** + * @param {bigint} handle + * @param {RustCallStatus} f_status_ + */ +export function ubrn_uniffi_matrix_rtc_fn_free_keyrejectedlistener(handle, f_status_) { + _assertClass(f_status_, RustCallStatus); + wasm.ubrn_uniffi_matrix_rtc_fn_free_keyrejectedlistener(handle, f_status_.__wbg_ptr); +} + +/** + * @param {any} vtable + */ +export function ubrn_uniffi_matrix_rtc_fn_init_callback_vtable_keyrejectedlistener(vtable) { + wasm.ubrn_uniffi_matrix_rtc_fn_init_callback_vtable_keyrejectedlistener(vtable); +} + +/** + * @param {bigint} ptr + * @param {Uint8Array} member_id + * @param {Uint8Array} reason + * @param {RustCallStatus} f_status_ + */ +export function ubrn_uniffi_matrix_rtc_fn_method_keyrejectedlistener_on_key_rejected(ptr, member_id, reason, f_status_) { + const ptr0 = passArray8ToWasm0(member_id, wasm.__wbindgen_malloc); + const len0 = WASM_VECTOR_LEN; + const ptr1 = passArray8ToWasm0(reason, wasm.__wbindgen_malloc); + const len1 = WASM_VECTOR_LEN; + _assertClass(f_status_, RustCallStatus); + wasm.ubrn_uniffi_matrix_rtc_fn_method_keyrejectedlistener_on_key_rejected(ptr, ptr0, len0, ptr1, len1, f_status_.__wbg_ptr); +} + +/** + * @param {bigint} ptr + * @param {RustCallStatus} f_status_ + * @returns {Uint8Array} + */ +export function ubrn_uniffi_matrix_rtc_fn_method_ffiparticipationmanager_own_membership(ptr, f_status_) { + _assertClass(f_status_, RustCallStatus); + const ret = wasm.ubrn_uniffi_matrix_rtc_fn_method_ffiparticipationmanager_own_membership(ptr, f_status_.__wbg_ptr); + var v1 = getArrayU8FromWasm0(ret[0], ret[1]).slice(); + wasm.__wbindgen_free(ret[0], ret[1] * 1, 1); + return v1; +} + +/** + * @param {bigint} ptr + * @param {RustCallStatus} f_status_ + * @returns {Uint8Array} + */ +export function ubrn_uniffi_matrix_rtc_fn_method_ffiparticipationmanager_own_transport_identity(ptr, f_status_) { + _assertClass(f_status_, RustCallStatus); + const ret = wasm.ubrn_uniffi_matrix_rtc_fn_method_ffiparticipationmanager_own_transport_identity(ptr, f_status_.__wbg_ptr); + var v1 = getArrayU8FromWasm0(ret[0], ret[1]).slice(); + wasm.__wbindgen_free(ret[0], ret[1] * 1, 1); + return v1; +} + +/** + * @param {bigint} ptr + * @param {RustCallStatus} f_status_ + * @returns {Uint8Array} + */ +export function ubrn_uniffi_matrix_rtc_fn_method_ffiparticipationmanager_session(ptr, f_status_) { + _assertClass(f_status_, RustCallStatus); + const ret = wasm.ubrn_uniffi_matrix_rtc_fn_method_ffiparticipationmanager_session(ptr, f_status_.__wbg_ptr); + var v1 = getArrayU8FromWasm0(ret[0], ret[1]).slice(); + wasm.__wbindgen_free(ret[0], ret[1] * 1, 1); + return v1; +} + +/** + * @param {bigint} ptr + * @param {bigint} listener + * @param {RustCallStatus} f_status_ + */ +export function ubrn_uniffi_matrix_rtc_fn_method_ffiparticipationmanager_set_connections_listener(ptr, listener, f_status_) { + _assertClass(f_status_, RustCallStatus); + wasm.ubrn_uniffi_matrix_rtc_fn_method_ffiparticipationmanager_set_connections_listener(ptr, listener, f_status_.__wbg_ptr); +} + +/** + * @param {bigint} ptr + * @param {bigint} listener + * @param {RustCallStatus} f_status_ + */ +export function ubrn_uniffi_matrix_rtc_fn_method_ffiparticipationmanager_set_key_map_listener(ptr, listener, f_status_) { + _assertClass(f_status_, RustCallStatus); + wasm.ubrn_uniffi_matrix_rtc_fn_method_ffiparticipationmanager_set_key_map_listener(ptr, listener, f_status_.__wbg_ptr); +} + +/** + * @param {bigint} ptr + * @param {bigint} listener + * @param {RustCallStatus} f_status_ + */ +export function ubrn_uniffi_matrix_rtc_fn_method_ffiparticipationmanager_set_key_rejected_listener(ptr, listener, f_status_) { + _assertClass(f_status_, RustCallStatus); + wasm.ubrn_uniffi_matrix_rtc_fn_method_ffiparticipationmanager_set_key_rejected_listener(ptr, listener, f_status_.__wbg_ptr); +} + +/** + * @param {bigint} ptr + * @param {bigint} listener + * @param {RustCallStatus} f_status_ + */ +export function ubrn_uniffi_matrix_rtc_fn_method_ffiparticipationmanager_set_memberships_listener(ptr, listener, f_status_) { + _assertClass(f_status_, RustCallStatus); + wasm.ubrn_uniffi_matrix_rtc_fn_method_ffiparticipationmanager_set_memberships_listener(ptr, listener, f_status_.__wbg_ptr); +} + +/** + * @param {bigint} ptr + * @param {bigint} listener + * @param {RustCallStatus} f_status_ + */ +export function ubrn_uniffi_matrix_rtc_fn_method_ffiparticipationmanager_set_status_listener(ptr, listener, f_status_) { + _assertClass(f_status_, RustCallStatus); + wasm.ubrn_uniffi_matrix_rtc_fn_method_ffiparticipationmanager_set_status_listener(ptr, listener, f_status_.__wbg_ptr); +} + +/** + * @param {bigint} ptr + * @param {RustCallStatus} f_status_ + * @returns {Uint8Array} + */ +export function ubrn_uniffi_matrix_rtc_fn_method_ffiparticipationmanager_status(ptr, f_status_) { + _assertClass(f_status_, RustCallStatus); + const ret = wasm.ubrn_uniffi_matrix_rtc_fn_method_ffiparticipationmanager_status(ptr, f_status_.__wbg_ptr); + var v1 = getArrayU8FromWasm0(ret[0], ret[1]).slice(); + wasm.__wbindgen_free(ret[0], ret[1] * 1, 1); + return v1; +} + +/** + * @param {bigint} handle + * @param {RustCallStatus} f_status_ + * @returns {bigint} + */ +export function ubrn_uniffi_matrix_rtc_fn_clone_matrixdrivercallback(handle, f_status_) { + _assertClass(f_status_, RustCallStatus); + const ret = wasm.ubrn_uniffi_matrix_rtc_fn_clone_matrixdrivercallback(handle, f_status_.__wbg_ptr); + return BigInt.asUintN(64, ret); +} + +/** + * @param {bigint} handle + * @param {RustCallStatus} f_status_ + */ +export function ubrn_uniffi_matrix_rtc_fn_free_matrixdrivercallback(handle, f_status_) { + _assertClass(f_status_, RustCallStatus); + wasm.ubrn_uniffi_matrix_rtc_fn_free_matrixdrivercallback(handle, f_status_.__wbg_ptr); +} + +/** + * @param {any} vtable + */ +export function ubrn_uniffi_matrix_rtc_fn_init_callback_vtable_matrixdrivercallback(vtable) { + wasm.ubrn_uniffi_matrix_rtc_fn_init_callback_vtable_matrixdrivercallback(vtable); +} + +/** + * @param {bigint} ptr + * @param {Uint8Array} request + * @returns {bigint} + */ +export function ubrn_uniffi_matrix_rtc_fn_method_matrixdrivercallback_get_livekit_token(ptr, request) { + const ptr0 = passArray8ToWasm0(request, wasm.__wbindgen_malloc); + const len0 = WASM_VECTOR_LEN; + const ret = wasm.ubrn_uniffi_matrix_rtc_fn_method_matrixdrivercallback_get_livekit_token(ptr, ptr0, len0); + return BigInt.asUintN(64, ret); +} + +/** + * @param {bigint} ptr + * @param {Uint8Array} event_type + * @param {Uint8Array} state_key + * @param {number} limit + * @returns {bigint} + */ +export function ubrn_uniffi_matrix_rtc_fn_method_matrixdrivercallback_read_events(ptr, event_type, state_key, limit) { + const ptr0 = passArray8ToWasm0(event_type, wasm.__wbindgen_malloc); + const len0 = WASM_VECTOR_LEN; + const ptr1 = passArray8ToWasm0(state_key, wasm.__wbindgen_malloc); + const len1 = WASM_VECTOR_LEN; + const ret = wasm.ubrn_uniffi_matrix_rtc_fn_method_matrixdrivercallback_read_events(ptr, ptr0, len0, ptr1, len1, limit); + return BigInt.asUintN(64, ret); +} + +/** + * @param {bigint} ptr + * @param {Uint8Array} event_type + * @param {Uint8Array} state_key + * @returns {bigint} + */ +export function ubrn_uniffi_matrix_rtc_fn_method_matrixdrivercallback_read_state(ptr, event_type, state_key) { + const ptr0 = passArray8ToWasm0(event_type, wasm.__wbindgen_malloc); + const len0 = WASM_VECTOR_LEN; + const ptr1 = passArray8ToWasm0(state_key, wasm.__wbindgen_malloc); + const len1 = WASM_VECTOR_LEN; + const ret = wasm.ubrn_uniffi_matrix_rtc_fn_method_matrixdrivercallback_read_state(ptr, ptr0, len0, ptr1, len1); + return BigInt.asUintN(64, ret); +} + +/** + * @param {bigint} ptr + * @param {bigint} sink + * @param {RustCallStatus} f_status_ + */ +export function ubrn_uniffi_matrix_rtc_fn_method_matrixdrivercallback_subscribe_room_events(ptr, sink, f_status_) { + _assertClass(f_status_, RustCallStatus); + wasm.ubrn_uniffi_matrix_rtc_fn_method_matrixdrivercallback_subscribe_room_events(ptr, sink, f_status_.__wbg_ptr); +} + +/** + * @param {bigint} ptr + * @param {bigint} sink + * @param {RustCallStatus} f_status_ + */ +export function ubrn_uniffi_matrix_rtc_fn_method_matrixdrivercallback_subscribe_to_device_events(ptr, sink, f_status_) { + _assertClass(f_status_, RustCallStatus); + wasm.ubrn_uniffi_matrix_rtc_fn_method_matrixdrivercallback_subscribe_to_device_events(ptr, sink, f_status_.__wbg_ptr); +} + +/** + * @param {bigint} ptr + * @param {bigint} sink + * @param {RustCallStatus} f_status_ + */ +export function ubrn_uniffi_matrix_rtc_fn_method_matrixdrivercallback_subscribe_state_updates(ptr, sink, f_status_) { + _assertClass(f_status_, RustCallStatus); + wasm.ubrn_uniffi_matrix_rtc_fn_method_matrixdrivercallback_subscribe_state_updates(ptr, sink, f_status_.__wbg_ptr); +} + +/** + * @param {bigint} ptr + * @param {RustCallStatus} f_status_ + * @returns {number} + */ +export function ubrn_uniffi_matrix_rtc_fn_method_matrixdrivercallback_is_homeserver_connected(ptr, f_status_) { + _assertClass(f_status_, RustCallStatus); + const ret = wasm.ubrn_uniffi_matrix_rtc_fn_method_matrixdrivercallback_is_homeserver_connected(ptr, f_status_.__wbg_ptr); + return ret; +} + +/** + * @param {bigint} ptr + * @param {bigint} sink + * @param {RustCallStatus} f_status_ + */ +export function ubrn_uniffi_matrix_rtc_fn_method_matrixdrivercallback_subscribe_connectivity(ptr, sink, f_status_) { + _assertClass(f_status_, RustCallStatus); + wasm.ubrn_uniffi_matrix_rtc_fn_method_matrixdrivercallback_subscribe_connectivity(ptr, sink, f_status_.__wbg_ptr); +} + +/** + * @param {bigint} ptr + * @param {Uint8Array} room_id + * @param {Uint8Array} event_type + * @param {Uint8Array} content_json + * @param {bigint} duration_ms + * @returns {bigint} + */ +export function ubrn_uniffi_matrix_rtc_fn_method_matrixdrivercallback_send_sticky_event(ptr, room_id, event_type, content_json, duration_ms) { + const ptr0 = passArray8ToWasm0(room_id, wasm.__wbindgen_malloc); + const len0 = WASM_VECTOR_LEN; + const ptr1 = passArray8ToWasm0(event_type, wasm.__wbindgen_malloc); + const len1 = WASM_VECTOR_LEN; + const ptr2 = passArray8ToWasm0(content_json, wasm.__wbindgen_malloc); + const len2 = WASM_VECTOR_LEN; + const ret = wasm.ubrn_uniffi_matrix_rtc_fn_method_matrixdrivercallback_send_sticky_event(ptr, ptr0, len0, ptr1, len1, ptr2, len2, duration_ms); + return BigInt.asUintN(64, ret); +} + +/** + * @param {bigint} ptr + * @param {Uint8Array} room_id + * @param {Uint8Array} event_type + * @param {Uint8Array} state_key + * @param {Uint8Array} content_json + * @returns {bigint} + */ +export function ubrn_uniffi_matrix_rtc_fn_method_matrixdrivercallback_send_state_event(ptr, room_id, event_type, state_key, content_json) { + const ptr0 = passArray8ToWasm0(room_id, wasm.__wbindgen_malloc); + const len0 = WASM_VECTOR_LEN; + const ptr1 = passArray8ToWasm0(event_type, wasm.__wbindgen_malloc); + const len1 = WASM_VECTOR_LEN; + const ptr2 = passArray8ToWasm0(state_key, wasm.__wbindgen_malloc); + const len2 = WASM_VECTOR_LEN; + const ptr3 = passArray8ToWasm0(content_json, wasm.__wbindgen_malloc); + const len3 = WASM_VECTOR_LEN; + const ret = wasm.ubrn_uniffi_matrix_rtc_fn_method_matrixdrivercallback_send_state_event(ptr, ptr0, len0, ptr1, len1, ptr2, len2, ptr3, len3); + return BigInt.asUintN(64, ret); +} + +/** + * @param {bigint} ptr + * @param {Uint8Array} room_id + * @param {Uint8Array} event_type + * @param {Uint8Array} content_json + * @param {bigint} delay_ms + * @param {Uint8Array} sticky_duration_ms + * @returns {bigint} + */ +export function ubrn_uniffi_matrix_rtc_fn_method_matrixdrivercallback_send_delayed_event(ptr, room_id, event_type, content_json, delay_ms, sticky_duration_ms) { + const ptr0 = passArray8ToWasm0(room_id, wasm.__wbindgen_malloc); + const len0 = WASM_VECTOR_LEN; + const ptr1 = passArray8ToWasm0(event_type, wasm.__wbindgen_malloc); + const len1 = WASM_VECTOR_LEN; + const ptr2 = passArray8ToWasm0(content_json, wasm.__wbindgen_malloc); + const len2 = WASM_VECTOR_LEN; + const ptr3 = passArray8ToWasm0(sticky_duration_ms, wasm.__wbindgen_malloc); + const len3 = WASM_VECTOR_LEN; + const ret = wasm.ubrn_uniffi_matrix_rtc_fn_method_matrixdrivercallback_send_delayed_event(ptr, ptr0, len0, ptr1, len1, ptr2, len2, delay_ms, ptr3, len3); + return BigInt.asUintN(64, ret); +} + +/** + * @param {bigint} ptr + * @param {Uint8Array} room_id + * @param {Uint8Array} event_type + * @param {Uint8Array} state_key + * @param {Uint8Array} content_json + * @param {bigint} delay_ms + * @returns {bigint} + */ +export function ubrn_uniffi_matrix_rtc_fn_method_matrixdrivercallback_send_delayed_state_event(ptr, room_id, event_type, state_key, content_json, delay_ms) { + const ptr0 = passArray8ToWasm0(room_id, wasm.__wbindgen_malloc); + const len0 = WASM_VECTOR_LEN; + const ptr1 = passArray8ToWasm0(event_type, wasm.__wbindgen_malloc); + const len1 = WASM_VECTOR_LEN; + const ptr2 = passArray8ToWasm0(state_key, wasm.__wbindgen_malloc); + const len2 = WASM_VECTOR_LEN; + const ptr3 = passArray8ToWasm0(content_json, wasm.__wbindgen_malloc); + const len3 = WASM_VECTOR_LEN; + const ret = wasm.ubrn_uniffi_matrix_rtc_fn_method_matrixdrivercallback_send_delayed_state_event(ptr, ptr0, len0, ptr1, len1, ptr2, len2, ptr3, len3, delay_ms); + return BigInt.asUintN(64, ret); +} + +/** + * @param {bigint} ptr + * @param {Uint8Array} room_id + * @param {Uint8Array} delay_id + * @returns {bigint} + */ +export function ubrn_uniffi_matrix_rtc_fn_method_matrixdrivercallback_restart_delayed_event(ptr, room_id, delay_id) { + const ptr0 = passArray8ToWasm0(room_id, wasm.__wbindgen_malloc); + const len0 = WASM_VECTOR_LEN; + const ptr1 = passArray8ToWasm0(delay_id, wasm.__wbindgen_malloc); + const len1 = WASM_VECTOR_LEN; + const ret = wasm.ubrn_uniffi_matrix_rtc_fn_method_matrixdrivercallback_restart_delayed_event(ptr, ptr0, len0, ptr1, len1); + return BigInt.asUintN(64, ret); +} + +/** + * @param {bigint} ptr + * @param {Uint8Array} room_id + * @param {Uint8Array} delay_id + * @returns {bigint} + */ +export function ubrn_uniffi_matrix_rtc_fn_method_matrixdrivercallback_cancel_delayed_event(ptr, room_id, delay_id) { + const ptr0 = passArray8ToWasm0(room_id, wasm.__wbindgen_malloc); + const len0 = WASM_VECTOR_LEN; + const ptr1 = passArray8ToWasm0(delay_id, wasm.__wbindgen_malloc); + const len1 = WASM_VECTOR_LEN; + const ret = wasm.ubrn_uniffi_matrix_rtc_fn_method_matrixdrivercallback_cancel_delayed_event(ptr, ptr0, len0, ptr1, len1); + return BigInt.asUintN(64, ret); +} + +/** + * @param {bigint} ptr + * @param {Uint8Array} room_id + * @param {Uint8Array} slot_id + * @param {Uint8Array} member_json + * @param {Uint8Array} delay_id + * @param {Uint8Array} livekit_service_url + * @param {bigint} delay_ms + * @returns {bigint} + */ +export function ubrn_uniffi_matrix_rtc_fn_method_matrixdrivercallback_delegate_livekit_delayed_leave(ptr, room_id, slot_id, member_json, delay_id, livekit_service_url, delay_ms) { + const ptr0 = passArray8ToWasm0(room_id, wasm.__wbindgen_malloc); + const len0 = WASM_VECTOR_LEN; + const ptr1 = passArray8ToWasm0(slot_id, wasm.__wbindgen_malloc); + const len1 = WASM_VECTOR_LEN; + const ptr2 = passArray8ToWasm0(member_json, wasm.__wbindgen_malloc); + const len2 = WASM_VECTOR_LEN; + const ptr3 = passArray8ToWasm0(delay_id, wasm.__wbindgen_malloc); + const len3 = WASM_VECTOR_LEN; + const ptr4 = passArray8ToWasm0(livekit_service_url, wasm.__wbindgen_malloc); + const len4 = WASM_VECTOR_LEN; + const ret = wasm.ubrn_uniffi_matrix_rtc_fn_method_matrixdrivercallback_delegate_livekit_delayed_leave(ptr, ptr0, len0, ptr1, len1, ptr2, len2, ptr3, len3, ptr4, len4, delay_ms); + return BigInt.asUintN(64, ret); +} + +/** + * @param {bigint} ptr + * @param {Uint8Array} recipients + * @param {Uint8Array} event_type + * @param {Uint8Array} content_json + * @returns {bigint} + */ +export function ubrn_uniffi_matrix_rtc_fn_method_matrixdrivercallback_send_to_device(ptr, recipients, event_type, content_json) { + const ptr0 = passArray8ToWasm0(recipients, wasm.__wbindgen_malloc); + const len0 = WASM_VECTOR_LEN; + const ptr1 = passArray8ToWasm0(event_type, wasm.__wbindgen_malloc); + const len1 = WASM_VECTOR_LEN; + const ptr2 = passArray8ToWasm0(content_json, wasm.__wbindgen_malloc); + const len2 = WASM_VECTOR_LEN; + const ret = wasm.ubrn_uniffi_matrix_rtc_fn_method_matrixdrivercallback_send_to_device(ptr, ptr0, len0, ptr1, len1, ptr2, len2); + return BigInt.asUintN(64, ret); +} + +/** + * @param {bigint} ptr + * @returns {bigint} + */ +export function ubrn_uniffi_matrix_rtc_fn_method_matrixdrivercallback_get_rtc_transports(ptr) { + const ret = wasm.ubrn_uniffi_matrix_rtc_fn_method_matrixdrivercallback_get_rtc_transports(ptr); + return BigInt.asUintN(64, ret); +} + +/** + * @param {bigint} handle + * @param {RustCallStatus} f_status_ + * @returns {bigint} + */ +export function ubrn_uniffi_matrix_rtc_fn_clone_membershipslistener(handle, f_status_) { + _assertClass(f_status_, RustCallStatus); + const ret = wasm.ubrn_uniffi_matrix_rtc_fn_clone_membershipslistener(handle, f_status_.__wbg_ptr); + return BigInt.asUintN(64, ret); +} + +/** + * @param {bigint} handle + * @param {RustCallStatus} f_status_ + */ +export function ubrn_uniffi_matrix_rtc_fn_free_membershipslistener(handle, f_status_) { + _assertClass(f_status_, RustCallStatus); + wasm.ubrn_uniffi_matrix_rtc_fn_free_membershipslistener(handle, f_status_.__wbg_ptr); +} + +/** + * @param {any} vtable + */ +export function ubrn_uniffi_matrix_rtc_fn_init_callback_vtable_membershipslistener(vtable) { + wasm.ubrn_uniffi_matrix_rtc_fn_init_callback_vtable_membershipslistener(vtable); +} + +/** + * @param {bigint} ptr + * @param {Uint8Array} memberships + * @param {RustCallStatus} f_status_ + */ +export function ubrn_uniffi_matrix_rtc_fn_method_membershipslistener_on_memberships_change(ptr, memberships, f_status_) { + const ptr0 = passArray8ToWasm0(memberships, wasm.__wbindgen_malloc); + const len0 = WASM_VECTOR_LEN; + _assertClass(f_status_, RustCallStatus); + wasm.ubrn_uniffi_matrix_rtc_fn_method_membershipslistener_on_memberships_change(ptr, ptr0, len0, f_status_.__wbg_ptr); +} + +/** + * @param {any} vtable + */ +export function ubrn_uniffi_matrix_rtc_fn_init_callback_vtable_statuslistener(vtable) { + wasm.ubrn_uniffi_matrix_rtc_fn_init_callback_vtable_statuslistener(vtable); +} + +/** + * @param {bigint} ptr + * @param {Uint8Array} status + * @param {RustCallStatus} f_status_ + */ +export function ubrn_uniffi_matrix_rtc_fn_method_statuslistener_on_status_change(ptr, status, f_status_) { + const ptr0 = passArray8ToWasm0(status, wasm.__wbindgen_malloc); + const len0 = WASM_VECTOR_LEN; + _assertClass(f_status_, RustCallStatus); + wasm.ubrn_uniffi_matrix_rtc_fn_method_statuslistener_on_status_change(ptr, ptr0, len0, f_status_.__wbg_ptr); +} + +/** + * @param {bigint} handle + * @param {RustCallStatus} f_status_ + * @returns {bigint} + */ +export function ubrn_uniffi_matrix_rtc_fn_clone_todevicesink(handle, f_status_) { + _assertClass(f_status_, RustCallStatus); + const ret = wasm.ubrn_uniffi_matrix_rtc_fn_clone_todevicesink(handle, f_status_.__wbg_ptr); + return BigInt.asUintN(64, ret); +} + +/** + * @param {bigint} handle + * @param {RustCallStatus} f_status_ + */ +export function ubrn_uniffi_matrix_rtc_fn_free_todevicesink(handle, f_status_) { + _assertClass(f_status_, RustCallStatus); + wasm.ubrn_uniffi_matrix_rtc_fn_free_todevicesink(handle, f_status_.__wbg_ptr); +} + +/** + * @param {bigint} ptr + * @param {Uint8Array} event_type + * @param {Uint8Array} sender + * @param {Uint8Array} content_json + * @param {Uint8Array} origin + * @param {Uint8Array} sender_cross_signed + * @param {RustCallStatus} f_status_ + * @returns {number} + */ +export function ubrn_uniffi_matrix_rtc_fn_method_todevicesink_emit(ptr, event_type, sender, content_json, origin, sender_cross_signed, f_status_) { + const ptr0 = passArray8ToWasm0(event_type, wasm.__wbindgen_malloc); + const len0 = WASM_VECTOR_LEN; + const ptr1 = passArray8ToWasm0(sender, wasm.__wbindgen_malloc); + const len1 = WASM_VECTOR_LEN; + const ptr2 = passArray8ToWasm0(content_json, wasm.__wbindgen_malloc); + const len2 = WASM_VECTOR_LEN; + const ptr3 = passArray8ToWasm0(origin, wasm.__wbindgen_malloc); + const len3 = WASM_VECTOR_LEN; + const ptr4 = passArray8ToWasm0(sender_cross_signed, wasm.__wbindgen_malloc); + const len4 = WASM_VECTOR_LEN; + _assertClass(f_status_, RustCallStatus); + const ret = wasm.ubrn_uniffi_matrix_rtc_fn_method_todevicesink_emit(ptr, ptr0, len0, ptr1, len1, ptr2, len2, ptr3, len3, ptr4, len4, f_status_.__wbg_ptr); + return ret; +} + +/** + * @param {Uint8Array} events_json + * @param {Uint8Array} compat + * @param {RustCallStatus} f_status_ + * @returns {Uint8Array} + */ +export function ubrn_uniffi_matrix_rtc_fn_func_compute_sessions_from_events(events_json, compat, f_status_) { + const ptr0 = passArray8ToWasm0(events_json, wasm.__wbindgen_malloc); + const len0 = WASM_VECTOR_LEN; + const ptr1 = passArray8ToWasm0(compat, wasm.__wbindgen_malloc); + const len1 = WASM_VECTOR_LEN; + _assertClass(f_status_, RustCallStatus); + const ret = wasm.ubrn_uniffi_matrix_rtc_fn_func_compute_sessions_from_events(ptr0, len0, ptr1, len1, f_status_.__wbg_ptr); + var v3 = getArrayU8FromWasm0(ret[0], ret[1]).slice(); + wasm.__wbindgen_free(ret[0], ret[1] * 1, 1); + return v3; +} + +/** + * @param {Uint8Array} impairment + * @param {RustCallStatus} f_status_ + * @returns {Uint8Array} + */ +export function ubrn_uniffi_matrix_rtc_fn_func_impairment_severity(impairment, f_status_) { + const ptr0 = passArray8ToWasm0(impairment, wasm.__wbindgen_malloc); + const len0 = WASM_VECTOR_LEN; + _assertClass(f_status_, RustCallStatus); + const ret = wasm.ubrn_uniffi_matrix_rtc_fn_func_impairment_severity(ptr0, len0, f_status_.__wbg_ptr); + var v2 = getArrayU8FromWasm0(ret[0], ret[1]).slice(); + wasm.__wbindgen_free(ret[0], ret[1] * 1, 1); + return v2; +} + +/** + * @param {bigint} handle + * @param {any} callback + * @param {bigint} callback_data + */ +export function ubrn_ffi_matrix_rtc_rust_future_poll_u8(handle, callback, callback_data) { + wasm.ubrn_ffi_matrix_rtc_rust_future_poll_u8(handle, callback, callback_data); +} + +/** + * @param {bigint} handle + */ +export function ubrn_ffi_matrix_rtc_rust_future_cancel_u8(handle) { + wasm.ubrn_ffi_matrix_rtc_rust_future_cancel_u8(handle); +} + +/** + * @param {bigint} handle + * @param {RustCallStatus} f_status_ + */ +export function ubrn_uniffi_matrix_rtc_fn_free_connectionslistener(handle, f_status_) { + _assertClass(f_status_, RustCallStatus); + wasm.ubrn_uniffi_matrix_rtc_fn_free_connectionslistener(handle, f_status_.__wbg_ptr); +} + +/** + * @param {bigint} handle + * @param {RustCallStatus} f_status_ + * @returns {bigint} + */ +export function ubrn_uniffi_matrix_rtc_fn_clone_roomeventsink(handle, f_status_) { + _assertClass(f_status_, RustCallStatus); + const ret = wasm.ubrn_uniffi_matrix_rtc_fn_clone_roomeventsink(handle, f_status_.__wbg_ptr); + return BigInt.asUintN(64, ret); +} + +/** + * @param {bigint} handle + * @param {RustCallStatus} f_status_ + */ +export function ubrn_uniffi_matrix_rtc_fn_free_roomeventsink(handle, f_status_) { + _assertClass(f_status_, RustCallStatus); + wasm.ubrn_uniffi_matrix_rtc_fn_free_roomeventsink(handle, f_status_.__wbg_ptr); +} + +/** + * @param {bigint} ptr + * @param {Uint8Array} event_json + * @param {Uint8Array} origin + * @param {RustCallStatus} f_status_ + * @returns {number} + */ +export function ubrn_uniffi_matrix_rtc_fn_method_roomeventsink_emit(ptr, event_json, origin, f_status_) { + const ptr0 = passArray8ToWasm0(event_json, wasm.__wbindgen_malloc); + const len0 = WASM_VECTOR_LEN; + const ptr1 = passArray8ToWasm0(origin, wasm.__wbindgen_malloc); + const len1 = WASM_VECTOR_LEN; + _assertClass(f_status_, RustCallStatus); + const ret = wasm.ubrn_uniffi_matrix_rtc_fn_method_roomeventsink_emit(ptr, ptr0, len0, ptr1, len1, f_status_.__wbg_ptr); + return ret; +} + +/** + * @param {bigint} handle + * @param {RustCallStatus} f_status_ + * @returns {bigint} + */ +export function ubrn_uniffi_matrix_rtc_fn_clone_stateupdatesink(handle, f_status_) { + _assertClass(f_status_, RustCallStatus); + const ret = wasm.ubrn_uniffi_matrix_rtc_fn_clone_stateupdatesink(handle, f_status_.__wbg_ptr); + return BigInt.asUintN(64, ret); +} + +/** + * @param {bigint} handle + * @param {RustCallStatus} f_status_ + */ +export function ubrn_uniffi_matrix_rtc_fn_free_stateupdatesink(handle, f_status_) { + _assertClass(f_status_, RustCallStatus); + wasm.ubrn_uniffi_matrix_rtc_fn_free_stateupdatesink(handle, f_status_.__wbg_ptr); +} + +/** + * @param {bigint} ptr + * @param {Uint8Array} events_json + * @param {RustCallStatus} f_status_ + * @returns {number} + */ +export function ubrn_uniffi_matrix_rtc_fn_method_stateupdatesink_emit(ptr, events_json, f_status_) { + const ptr0 = passArray8ToWasm0(events_json, wasm.__wbindgen_malloc); + const len0 = WASM_VECTOR_LEN; + _assertClass(f_status_, RustCallStatus); + const ret = wasm.ubrn_uniffi_matrix_rtc_fn_method_stateupdatesink_emit(ptr, ptr0, len0, f_status_.__wbg_ptr); + return ret; +} + +/** + * @param {bigint} handle + * @param {RustCallStatus} f_status_ + * @returns {bigint} + */ +export function ubrn_uniffi_matrix_rtc_fn_clone_statuslistener(handle, f_status_) { + _assertClass(f_status_, RustCallStatus); + const ret = wasm.ubrn_uniffi_matrix_rtc_fn_clone_statuslistener(handle, f_status_.__wbg_ptr); + return BigInt.asUintN(64, ret); +} + +/** + * @param {bigint} handle + * @param {RustCallStatus} f_status_ + */ +export function ubrn_uniffi_matrix_rtc_fn_free_statuslistener(handle, f_status_) { + _assertClass(f_status_, RustCallStatus); + wasm.ubrn_uniffi_matrix_rtc_fn_free_statuslistener(handle, f_status_.__wbg_ptr); +} + +/** + * @param {bigint} handle + */ +export function ubrn_ffi_matrix_rtc_rust_future_free_u8(handle) { + wasm.ubrn_ffi_matrix_rtc_rust_future_free_u8(handle); +} + +/** + * @param {bigint} handle + * @param {RustCallStatus} f_status_ + * @returns {number} + */ +export function ubrn_ffi_matrix_rtc_rust_future_complete_u8(handle, f_status_) { + _assertClass(f_status_, RustCallStatus); + const ret = wasm.ubrn_ffi_matrix_rtc_rust_future_complete_u8(handle, f_status_.__wbg_ptr); + return ret; +} + +/** + * @param {bigint} handle + * @param {any} callback + * @param {bigint} callback_data + */ +export function ubrn_ffi_matrix_rtc_rust_future_poll_i8(handle, callback, callback_data) { + wasm.ubrn_ffi_matrix_rtc_rust_future_poll_i8(handle, callback, callback_data); +} + +/** + * @param {bigint} handle + */ +export function ubrn_ffi_matrix_rtc_rust_future_free_i16(handle) { + wasm.ubrn_ffi_matrix_rtc_rust_future_free_i16(handle); +} + +/** + * @param {bigint} handle + * @param {RustCallStatus} f_status_ + * @returns {number} + */ +export function ubrn_ffi_matrix_rtc_rust_future_complete_i16(handle, f_status_) { + _assertClass(f_status_, RustCallStatus); + const ret = wasm.ubrn_ffi_matrix_rtc_rust_future_complete_i16(handle, f_status_.__wbg_ptr); + return ret; +} + +/** + * @param {bigint} handle + * @param {any} callback + * @param {bigint} callback_data + */ +export function ubrn_ffi_matrix_rtc_rust_future_poll_u32(handle, callback, callback_data) { + wasm.ubrn_ffi_matrix_rtc_rust_future_poll_u32(handle, callback, callback_data); +} + +/** + * @param {bigint} handle + */ +export function ubrn_ffi_matrix_rtc_rust_future_cancel_u32(handle) { + wasm.ubrn_ffi_matrix_rtc_rust_future_cancel_u32(handle); +} + +/** + * @param {bigint} handle + */ +export function ubrn_ffi_matrix_rtc_rust_future_free_u32(handle) { + wasm.ubrn_ffi_matrix_rtc_rust_future_free_u32(handle); +} + +/** + * @param {bigint} handle + * @param {RustCallStatus} f_status_ + * @returns {number} + */ +export function ubrn_ffi_matrix_rtc_rust_future_complete_u32(handle, f_status_) { + _assertClass(f_status_, RustCallStatus); + const ret = wasm.ubrn_ffi_matrix_rtc_rust_future_complete_u32(handle, f_status_.__wbg_ptr); + return ret >>> 0; +} + +/** + * @param {bigint} handle + * @param {any} callback + * @param {bigint} callback_data + */ +export function ubrn_ffi_matrix_rtc_rust_future_poll_i32(handle, callback, callback_data) { + wasm.ubrn_ffi_matrix_rtc_rust_future_poll_i32(handle, callback, callback_data); +} + +/** + * @param {bigint} handle + */ +export function ubrn_ffi_matrix_rtc_rust_future_cancel_i32(handle) { + wasm.ubrn_ffi_matrix_rtc_rust_future_cancel_i32(handle); +} + +/** + * @param {bigint} handle + */ +export function ubrn_ffi_matrix_rtc_rust_future_free_i32(handle) { + wasm.ubrn_ffi_matrix_rtc_rust_future_free_i32(handle); +} + +/** + * @param {bigint} handle + */ +export function ubrn_ffi_matrix_rtc_rust_future_cancel_i8(handle) { + wasm.ubrn_ffi_matrix_rtc_rust_future_cancel_i8(handle); +} + +/** + * @param {bigint} handle + */ +export function ubrn_ffi_matrix_rtc_rust_future_free_i8(handle) { + wasm.ubrn_ffi_matrix_rtc_rust_future_free_i8(handle); +} + +/** + * @param {bigint} handle + * @param {RustCallStatus} f_status_ + * @returns {number} + */ +export function ubrn_ffi_matrix_rtc_rust_future_complete_i8(handle, f_status_) { + _assertClass(f_status_, RustCallStatus); + const ret = wasm.ubrn_ffi_matrix_rtc_rust_future_complete_i8(handle, f_status_.__wbg_ptr); + return ret; +} + +/** + * @param {bigint} handle + * @param {any} callback + * @param {bigint} callback_data + */ +export function ubrn_ffi_matrix_rtc_rust_future_poll_u16(handle, callback, callback_data) { + wasm.ubrn_ffi_matrix_rtc_rust_future_poll_u16(handle, callback, callback_data); +} + +/** + * @param {bigint} handle + */ +export function ubrn_ffi_matrix_rtc_rust_future_cancel_u16(handle) { + wasm.ubrn_ffi_matrix_rtc_rust_future_cancel_u16(handle); +} + +/** + * @param {bigint} handle + */ +export function ubrn_ffi_matrix_rtc_rust_future_free_u16(handle) { + wasm.ubrn_ffi_matrix_rtc_rust_future_free_u16(handle); +} + +/** + * @param {bigint} handle + * @param {RustCallStatus} f_status_ + * @returns {number} + */ +export function ubrn_ffi_matrix_rtc_rust_future_complete_u16(handle, f_status_) { + _assertClass(f_status_, RustCallStatus); + const ret = wasm.ubrn_ffi_matrix_rtc_rust_future_complete_u16(handle, f_status_.__wbg_ptr); + return ret; +} + +/** + * @param {bigint} handle + * @param {any} callback + * @param {bigint} callback_data + */ +export function ubrn_ffi_matrix_rtc_rust_future_poll_i16(handle, callback, callback_data) { + wasm.ubrn_ffi_matrix_rtc_rust_future_poll_i16(handle, callback, callback_data); +} + +/** + * @param {bigint} handle + */ +export function ubrn_ffi_matrix_rtc_rust_future_cancel_i16(handle) { + wasm.ubrn_ffi_matrix_rtc_rust_future_cancel_i16(handle); +} + +/** + * @param {bigint} handle + * @param {RustCallStatus} f_status_ + * @returns {number} + */ +export function ubrn_ffi_matrix_rtc_rust_future_complete_i32(handle, f_status_) { + _assertClass(f_status_, RustCallStatus); + const ret = wasm.ubrn_ffi_matrix_rtc_rust_future_complete_i32(handle, f_status_.__wbg_ptr); + return ret; +} + +/** + * @param {bigint} handle + * @param {any} callback + * @param {bigint} callback_data + */ +export function ubrn_ffi_matrix_rtc_rust_future_poll_u64(handle, callback, callback_data) { + wasm.ubrn_ffi_matrix_rtc_rust_future_poll_u64(handle, callback, callback_data); +} + +/** + * @param {bigint} handle + */ +export function ubrn_ffi_matrix_rtc_rust_future_cancel_u64(handle) { + wasm.ubrn_ffi_matrix_rtc_rust_future_cancel_u64(handle); +} + +/** + * @param {bigint} handle + * @param {RustCallStatus} f_status_ + * @returns {number} + */ +export function ubrn_ffi_matrix_rtc_rust_future_complete_f32(handle, f_status_) { + _assertClass(f_status_, RustCallStatus); + const ret = wasm.ubrn_ffi_matrix_rtc_rust_future_complete_f32(handle, f_status_.__wbg_ptr); + return ret; +} + +/** + * @param {bigint} handle + * @param {any} callback + * @param {bigint} callback_data + */ +export function ubrn_ffi_matrix_rtc_rust_future_poll_f64(handle, callback, callback_data) { + wasm.ubrn_ffi_matrix_rtc_rust_future_poll_f64(handle, callback, callback_data); +} + +/** + * @param {bigint} handle + */ +export function ubrn_ffi_matrix_rtc_rust_future_cancel_f64(handle) { + wasm.ubrn_ffi_matrix_rtc_rust_future_cancel_f64(handle); +} + +/** + * @param {bigint} handle + */ +export function ubrn_ffi_matrix_rtc_rust_future_free_f64(handle) { + wasm.ubrn_ffi_matrix_rtc_rust_future_free_f64(handle); +} + +/** + * @param {bigint} handle + * @param {RustCallStatus} f_status_ + * @returns {number} + */ +export function ubrn_ffi_matrix_rtc_rust_future_complete_f64(handle, f_status_) { + _assertClass(f_status_, RustCallStatus); + const ret = wasm.ubrn_ffi_matrix_rtc_rust_future_complete_f64(handle, f_status_.__wbg_ptr); + return ret; +} + +/** + * @param {bigint} handle + * @param {any} callback + * @param {bigint} callback_data + */ +export function ubrn_ffi_matrix_rtc_rust_future_poll_rust_buffer(handle, callback, callback_data) { + wasm.ubrn_ffi_matrix_rtc_rust_future_poll_rust_buffer(handle, callback, callback_data); +} + +/** + * @param {bigint} handle + */ +export function ubrn_ffi_matrix_rtc_rust_future_cancel_rust_buffer(handle) { + wasm.ubrn_ffi_matrix_rtc_rust_future_cancel_rust_buffer(handle); +} + +/** + * @param {bigint} handle + */ +export function ubrn_ffi_matrix_rtc_rust_future_free_rust_buffer(handle) { + wasm.ubrn_ffi_matrix_rtc_rust_future_free_rust_buffer(handle); +} + +/** + * @param {bigint} handle + */ +export function ubrn_ffi_matrix_rtc_rust_future_free_u64(handle) { + wasm.ubrn_ffi_matrix_rtc_rust_future_free_u64(handle); +} + +/** + * @param {bigint} handle + * @param {RustCallStatus} f_status_ + * @returns {bigint} + */ +export function ubrn_ffi_matrix_rtc_rust_future_complete_u64(handle, f_status_) { + _assertClass(f_status_, RustCallStatus); + const ret = wasm.ubrn_ffi_matrix_rtc_rust_future_complete_u64(handle, f_status_.__wbg_ptr); + return BigInt.asUintN(64, ret); +} + +/** + * @param {bigint} handle + * @param {any} callback + * @param {bigint} callback_data + */ +export function ubrn_ffi_matrix_rtc_rust_future_poll_i64(handle, callback, callback_data) { + wasm.ubrn_ffi_matrix_rtc_rust_future_poll_i64(handle, callback, callback_data); +} + +/** + * @param {bigint} handle + */ +export function ubrn_ffi_matrix_rtc_rust_future_cancel_i64(handle) { + wasm.ubrn_ffi_matrix_rtc_rust_future_cancel_i64(handle); +} + +/** + * @param {bigint} handle + */ +export function ubrn_ffi_matrix_rtc_rust_future_free_i64(handle) { + wasm.ubrn_ffi_matrix_rtc_rust_future_free_i64(handle); +} + +/** + * @param {bigint} handle + * @param {RustCallStatus} f_status_ + * @returns {bigint} + */ +export function ubrn_ffi_matrix_rtc_rust_future_complete_i64(handle, f_status_) { + _assertClass(f_status_, RustCallStatus); + const ret = wasm.ubrn_ffi_matrix_rtc_rust_future_complete_i64(handle, f_status_.__wbg_ptr); + return ret; +} + +/** + * @param {bigint} handle + * @param {any} callback + * @param {bigint} callback_data + */ +export function ubrn_ffi_matrix_rtc_rust_future_poll_f32(handle, callback, callback_data) { + wasm.ubrn_ffi_matrix_rtc_rust_future_poll_f32(handle, callback, callback_data); +} + +/** + * @param {bigint} handle + */ +export function ubrn_ffi_matrix_rtc_rust_future_cancel_f32(handle) { + wasm.ubrn_ffi_matrix_rtc_rust_future_cancel_f32(handle); +} + +/** + * @param {bigint} handle + */ +export function ubrn_ffi_matrix_rtc_rust_future_free_f32(handle) { + wasm.ubrn_ffi_matrix_rtc_rust_future_free_f32(handle); +} + +/** + * @param {bigint} handle + * @param {RustCallStatus} f_status_ + * @returns {Uint8Array} + */ +export function ubrn_ffi_matrix_rtc_rust_future_complete_rust_buffer(handle, f_status_) { + _assertClass(f_status_, RustCallStatus); + const ret = wasm.ubrn_ffi_matrix_rtc_rust_future_complete_rust_buffer(handle, f_status_.__wbg_ptr); + var v1 = getArrayU8FromWasm0(ret[0], ret[1]).slice(); + wasm.__wbindgen_free(ret[0], ret[1] * 1, 1); + return v1; +} + +/** + * @param {bigint} handle + * @param {any} callback + * @param {bigint} callback_data + */ +export function ubrn_ffi_matrix_rtc_rust_future_poll_void(handle, callback, callback_data) { + wasm.ubrn_ffi_matrix_rtc_rust_future_poll_void(handle, callback, callback_data); +} + +/** + * @param {bigint} handle + */ +export function ubrn_ffi_matrix_rtc_rust_future_cancel_void(handle) { + wasm.ubrn_ffi_matrix_rtc_rust_future_cancel_void(handle); +} + +/** + * @param {bigint} handle + */ +export function ubrn_ffi_matrix_rtc_rust_future_free_void(handle) { + wasm.ubrn_ffi_matrix_rtc_rust_future_free_void(handle); +} + +/** + * @returns {number} + */ +export function ubrn_uniffi_matrix_rtc_checksum_method_ffiparticipationmanager_debug_snapshot() { + const ret = wasm.ubrn_uniffi_matrix_rtc_checksum_method_ffiparticipationmanager_debug_snapshot(); + return ret; +} + +/** + * @returns {number} + */ +export function ubrn_uniffi_matrix_rtc_checksum_method_ffiparticipationmanager_is_homeserver_connected() { + const ret = wasm.ubrn_uniffi_matrix_rtc_checksum_method_ffiparticipationmanager_is_homeserver_connected(); + return ret; +} + +/** + * @returns {number} + */ +export function ubrn_uniffi_matrix_rtc_checksum_method_ffiparticipationmanager_join() { + const ret = wasm.ubrn_uniffi_matrix_rtc_checksum_method_ffiparticipationmanager_join(); + return ret; +} + +/** + * @returns {number} + */ +export function ubrn_uniffi_matrix_rtc_checksum_method_ffiparticipationmanager_key_map() { + const ret = wasm.ubrn_uniffi_matrix_rtc_checksum_method_ffiparticipationmanager_key_map(); + return ret; +} + +/** + * @returns {number} + */ +export function ubrn_uniffi_matrix_rtc_checksum_method_ffiparticipationmanager_leave() { + const ret = wasm.ubrn_uniffi_matrix_rtc_checksum_method_ffiparticipationmanager_leave(); + return ret; +} + +/** + * @returns {number} + */ +export function ubrn_uniffi_matrix_rtc_checksum_method_ffiparticipationmanager_memberships() { + const ret = wasm.ubrn_uniffi_matrix_rtc_checksum_method_ffiparticipationmanager_memberships(); + return ret; +} + +/** + * @returns {number} + */ +export function ubrn_uniffi_matrix_rtc_checksum_method_ffiparticipationmanager_open_slot() { + const ret = wasm.ubrn_uniffi_matrix_rtc_checksum_method_ffiparticipationmanager_open_slot(); + return ret; +} + +/** + * @returns {number} + */ +export function ubrn_uniffi_matrix_rtc_checksum_method_ffiparticipationmanager_own_member_id() { + const ret = wasm.ubrn_uniffi_matrix_rtc_checksum_method_ffiparticipationmanager_own_member_id(); + return ret; +} + +/** + * @returns {number} + */ +export function ubrn_uniffi_matrix_rtc_checksum_method_ffiparticipationmanager_own_membership() { + const ret = wasm.ubrn_uniffi_matrix_rtc_checksum_method_ffiparticipationmanager_own_membership(); + return ret; +} + +/** + * @param {any} vtable + */ +export function ubrn_uniffi_matrix_rtc_fn_init_callback_vtable_connectionslistener(vtable) { + wasm.ubrn_uniffi_matrix_rtc_fn_init_callback_vtable_connectionslistener(vtable); +} + +/** + * @param {bigint} handle + * @param {RustCallStatus} f_status_ + */ +export function ubrn_ffi_matrix_rtc_rust_future_complete_void(handle, f_status_) { + _assertClass(f_status_, RustCallStatus); + wasm.ubrn_ffi_matrix_rtc_rust_future_complete_void(handle, f_status_.__wbg_ptr); +} + +/** + * @returns {number} + */ +export function ubrn_uniffi_matrix_rtc_checksum_func_compute_sessions_from_events() { + const ret = wasm.ubrn_uniffi_matrix_rtc_checksum_func_compute_sessions_from_events(); + return ret; +} + +/** + * @returns {number} + */ +export function ubrn_uniffi_matrix_rtc_checksum_func_impairment_severity() { + const ret = wasm.ubrn_uniffi_matrix_rtc_checksum_func_impairment_severity(); + return ret; +} + +/** + * @returns {number} + */ +export function ubrn_uniffi_matrix_rtc_checksum_method_connectionslistener_on_connections_change() { + const ret = wasm.ubrn_uniffi_matrix_rtc_checksum_method_connectionslistener_on_connections_change(); + return ret; +} + +/** + * @returns {number} + */ +export function ubrn_uniffi_matrix_rtc_checksum_method_connectivitysink_emit() { + const ret = wasm.ubrn_uniffi_matrix_rtc_checksum_method_connectivitysink_emit(); + return ret; +} + +/** + * @returns {number} + */ +export function ubrn_uniffi_matrix_rtc_checksum_method_ffiparticipationmanager_close_slot() { + const ret = wasm.ubrn_uniffi_matrix_rtc_checksum_method_ffiparticipationmanager_close_slot(); + return ret; +} + +/** + * @returns {number} + */ +export function ubrn_uniffi_matrix_rtc_checksum_method_ffiparticipationmanager_connection_problems() { + const ret = wasm.ubrn_uniffi_matrix_rtc_checksum_method_ffiparticipationmanager_connection_problems(); + return ret; +} + +/** + * @returns {number} + */ +export function ubrn_uniffi_matrix_rtc_checksum_method_ffiparticipationmanager_connections() { + const ret = wasm.ubrn_uniffi_matrix_rtc_checksum_method_ffiparticipationmanager_connections(); + return ret; +} + +/** + * @returns {number} + */ +export function ubrn_uniffi_matrix_rtc_checksum_method_ffiparticipationmanager_own_transport_identity() { + const ret = wasm.ubrn_uniffi_matrix_rtc_checksum_method_ffiparticipationmanager_own_transport_identity(); + return ret; +} + +/** + * @returns {number} + */ +export function ubrn_uniffi_matrix_rtc_checksum_method_ffiparticipationmanager_session() { + const ret = wasm.ubrn_uniffi_matrix_rtc_checksum_method_ffiparticipationmanager_session(); + return ret; +} + +/** + * @returns {number} + */ +export function ubrn_uniffi_matrix_rtc_checksum_method_ffiparticipationmanager_set_connections_listener() { + const ret = wasm.ubrn_uniffi_matrix_rtc_checksum_method_ffiparticipationmanager_set_connections_listener(); + return ret; +} + +/** + * @returns {number} + */ +export function ubrn_uniffi_matrix_rtc_checksum_method_matrixdrivercallback_send_state_event() { + const ret = wasm.ubrn_uniffi_matrix_rtc_checksum_method_matrixdrivercallback_send_state_event(); + return ret; +} + +/** + * @returns {number} + */ +export function ubrn_uniffi_matrix_rtc_checksum_method_matrixdrivercallback_send_delayed_event() { + const ret = wasm.ubrn_uniffi_matrix_rtc_checksum_method_matrixdrivercallback_send_delayed_event(); + return ret; +} + +/** + * @returns {number} + */ +export function ubrn_uniffi_matrix_rtc_checksum_method_matrixdrivercallback_send_delayed_state_event() { + const ret = wasm.ubrn_uniffi_matrix_rtc_checksum_method_matrixdrivercallback_send_delayed_state_event(); + return ret; +} + +/** + * @returns {number} + */ +export function ubrn_uniffi_matrix_rtc_checksum_method_matrixdrivercallback_restart_delayed_event() { + const ret = wasm.ubrn_uniffi_matrix_rtc_checksum_method_matrixdrivercallback_restart_delayed_event(); + return ret; +} + +/** + * @returns {number} + */ +export function ubrn_uniffi_matrix_rtc_checksum_method_matrixdrivercallback_cancel_delayed_event() { + const ret = wasm.ubrn_uniffi_matrix_rtc_checksum_method_matrixdrivercallback_cancel_delayed_event(); + return ret; +} + +/** + * @returns {number} + */ +export function ubrn_uniffi_matrix_rtc_checksum_method_matrixdrivercallback_delegate_livekit_delayed_leave() { + const ret = wasm.ubrn_uniffi_matrix_rtc_checksum_method_matrixdrivercallback_delegate_livekit_delayed_leave(); + return ret; +} + +/** + * @returns {number} + */ +export function ubrn_uniffi_matrix_rtc_checksum_method_matrixdrivercallback_send_to_device() { + const ret = wasm.ubrn_uniffi_matrix_rtc_checksum_method_matrixdrivercallback_send_to_device(); + return ret; +} + +/** + * @returns {number} + */ +export function ubrn_uniffi_matrix_rtc_checksum_method_matrixdrivercallback_get_rtc_transports() { + const ret = wasm.ubrn_uniffi_matrix_rtc_checksum_method_matrixdrivercallback_get_rtc_transports(); + return ret; +} + +/** + * @returns {number} + */ +export function ubrn_uniffi_matrix_rtc_checksum_method_matrixdrivercallback_get_livekit_token() { + const ret = wasm.ubrn_uniffi_matrix_rtc_checksum_method_matrixdrivercallback_get_livekit_token(); + return ret; +} + +/** + * @returns {number} + */ +export function ubrn_uniffi_matrix_rtc_checksum_method_ffiparticipationmanager_set_key_map_listener() { + const ret = wasm.ubrn_uniffi_matrix_rtc_checksum_method_ffiparticipationmanager_set_key_map_listener(); + return ret; +} + +/** + * @returns {number} + */ +export function ubrn_uniffi_matrix_rtc_checksum_method_ffiparticipationmanager_set_key_rejected_listener() { + const ret = wasm.ubrn_uniffi_matrix_rtc_checksum_method_ffiparticipationmanager_set_key_rejected_listener(); + return ret; +} + +/** + * @returns {number} + */ +export function ubrn_uniffi_matrix_rtc_checksum_method_ffiparticipationmanager_set_memberships_listener() { + const ret = wasm.ubrn_uniffi_matrix_rtc_checksum_method_ffiparticipationmanager_set_memberships_listener(); + return ret; +} + +/** + * @returns {number} + */ +export function ubrn_uniffi_matrix_rtc_checksum_method_ffiparticipationmanager_set_status_listener() { + const ret = wasm.ubrn_uniffi_matrix_rtc_checksum_method_ffiparticipationmanager_set_status_listener(); + return ret; +} + +/** + * @returns {number} + */ +export function ubrn_uniffi_matrix_rtc_checksum_method_ffiparticipationmanager_status() { + const ret = wasm.ubrn_uniffi_matrix_rtc_checksum_method_ffiparticipationmanager_status(); + return ret; +} + +/** + * @returns {number} + */ +export function ubrn_uniffi_matrix_rtc_checksum_method_ffiparticipationmanager_update_application() { + const ret = wasm.ubrn_uniffi_matrix_rtc_checksum_method_ffiparticipationmanager_update_application(); + return ret; +} + +/** + * @returns {number} + */ +export function ubrn_uniffi_matrix_rtc_checksum_method_keymaplistener_on_key_map_change() { + const ret = wasm.ubrn_uniffi_matrix_rtc_checksum_method_keymaplistener_on_key_map_change(); + return ret; +} + +/** + * @returns {number} + */ +export function ubrn_uniffi_matrix_rtc_checksum_method_keyrejectedlistener_on_key_rejected() { + const ret = wasm.ubrn_uniffi_matrix_rtc_checksum_method_keyrejectedlistener_on_key_rejected(); + return ret; +} + +/** + * @returns {number} + */ +export function ubrn_uniffi_matrix_rtc_checksum_method_matrixdrivercallback_send_sticky_event() { + const ret = wasm.ubrn_uniffi_matrix_rtc_checksum_method_matrixdrivercallback_send_sticky_event(); + return ret; +} + +/** + * @returns {number} + */ +export function ubrn_uniffi_matrix_rtc_checksum_method_matrixdrivercallback_read_events() { + const ret = wasm.ubrn_uniffi_matrix_rtc_checksum_method_matrixdrivercallback_read_events(); + return ret; +} + +/** + * @returns {number} + */ +export function ubrn_uniffi_matrix_rtc_checksum_method_matrixdrivercallback_read_state() { + const ret = wasm.ubrn_uniffi_matrix_rtc_checksum_method_matrixdrivercallback_read_state(); + return ret; +} + +/** + * @returns {number} + */ +export function ubrn_uniffi_matrix_rtc_checksum_method_matrixdrivercallback_subscribe_room_events() { + const ret = wasm.ubrn_uniffi_matrix_rtc_checksum_method_matrixdrivercallback_subscribe_room_events(); + return ret; +} + +/** + * @returns {number} + */ +export function ubrn_uniffi_matrix_rtc_checksum_constructor_ffimatrixdriver_new() { + const ret = wasm.ubrn_uniffi_matrix_rtc_checksum_constructor_ffimatrixdriver_new(); + return ret; +} + +/** + * @returns {number} + */ +export function ubrn_uniffi_matrix_rtc_checksum_constructor_ffiparticipationmanager_new() { + const ret = wasm.ubrn_uniffi_matrix_rtc_checksum_constructor_ffiparticipationmanager_new(); + return ret; +} + +/** + * @returns {number} + */ +export function ubrn_ffi_matrix_rtc_uniffi_contract_version() { + const ret = wasm.ubrn_ffi_matrix_rtc_uniffi_contract_version(); + return ret >>> 0; +} + +/** + * @returns {number} + */ +export function ubrn_uniffi_matrix_rtc_checksum_method_matrixdrivercallback_subscribe_to_device_events() { + const ret = wasm.ubrn_uniffi_matrix_rtc_checksum_method_matrixdrivercallback_subscribe_to_device_events(); + return ret; +} + +/** + * @returns {number} + */ +export function ubrn_uniffi_matrix_rtc_checksum_method_matrixdrivercallback_subscribe_state_updates() { + const ret = wasm.ubrn_uniffi_matrix_rtc_checksum_method_matrixdrivercallback_subscribe_state_updates(); + return ret; +} + +/** + * @returns {number} + */ +export function ubrn_uniffi_matrix_rtc_checksum_method_matrixdrivercallback_is_homeserver_connected() { + const ret = wasm.ubrn_uniffi_matrix_rtc_checksum_method_matrixdrivercallback_is_homeserver_connected(); + return ret; +} + +/** + * @returns {number} + */ +export function ubrn_uniffi_matrix_rtc_checksum_method_matrixdrivercallback_subscribe_connectivity() { + const ret = wasm.ubrn_uniffi_matrix_rtc_checksum_method_matrixdrivercallback_subscribe_connectivity(); + return ret; +} + +/** + * @returns {number} + */ +export function ubrn_uniffi_matrix_rtc_checksum_method_membershipslistener_on_memberships_change() { + const ret = wasm.ubrn_uniffi_matrix_rtc_checksum_method_membershipslistener_on_memberships_change(); + return ret; +} + +/** + * @returns {number} + */ +export function ubrn_uniffi_matrix_rtc_checksum_method_roomeventsink_emit() { + const ret = wasm.ubrn_uniffi_matrix_rtc_checksum_method_roomeventsink_emit(); + return ret; +} + +/** + * @returns {number} + */ +export function ubrn_uniffi_matrix_rtc_checksum_method_stateupdatesink_emit() { + const ret = wasm.ubrn_uniffi_matrix_rtc_checksum_method_stateupdatesink_emit(); + return ret; +} + +/** + * @returns {number} + */ +export function ubrn_uniffi_matrix_rtc_checksum_method_statuslistener_on_status_change() { + const ret = wasm.ubrn_uniffi_matrix_rtc_checksum_method_statuslistener_on_status_change(); + return ret; +} + +/** + * @returns {number} + */ +export function ubrn_uniffi_matrix_rtc_checksum_method_todevicesink_emit() { + const ret = wasm.ubrn_uniffi_matrix_rtc_checksum_method_todevicesink_emit(); + return ret; +} + +/** + * @param {bigint} ptr + * @param {Uint8Array} connections + * @param {RustCallStatus} f_status_ + */ +export function ubrn_uniffi_matrix_rtc_fn_method_connectionslistener_on_connections_change(ptr, connections, f_status_) { + const ptr0 = passArray8ToWasm0(connections, wasm.__wbindgen_malloc); + const len0 = WASM_VECTOR_LEN; + _assertClass(f_status_, RustCallStatus); + wasm.ubrn_uniffi_matrix_rtc_fn_method_connectionslistener_on_connections_change(ptr, ptr0, len0, f_status_.__wbg_ptr); +} + +/** + * @param {Uint8Array} room_id + * @param {Uint8Array} slot_id + * @param {Uint8Array} user_id + * @param {Uint8Array} device_id + * @param {bigint} driver + * @param {Uint8Array} config + * @param {RustCallStatus} f_status_ + * @returns {bigint} + */ +export function ubrn_uniffi_matrix_rtc_fn_constructor_ffiparticipationmanager_new(room_id, slot_id, user_id, device_id, driver, config, f_status_) { + const ptr0 = passArray8ToWasm0(room_id, wasm.__wbindgen_malloc); + const len0 = WASM_VECTOR_LEN; + const ptr1 = passArray8ToWasm0(slot_id, wasm.__wbindgen_malloc); + const len1 = WASM_VECTOR_LEN; + const ptr2 = passArray8ToWasm0(user_id, wasm.__wbindgen_malloc); + const len2 = WASM_VECTOR_LEN; + const ptr3 = passArray8ToWasm0(device_id, wasm.__wbindgen_malloc); + const len3 = WASM_VECTOR_LEN; + const ptr4 = passArray8ToWasm0(config, wasm.__wbindgen_malloc); + const len4 = WASM_VECTOR_LEN; + _assertClass(f_status_, RustCallStatus); + const ret = wasm.ubrn_uniffi_matrix_rtc_fn_constructor_ffiparticipationmanager_new(ptr0, len0, ptr1, len1, ptr2, len2, ptr3, len3, driver, ptr4, len4, f_status_.__wbg_ptr); + return BigInt.asUintN(64, ret); +} + +/** + * @param {bigint} ptr + * @returns {bigint} + */ +export function ubrn_uniffi_matrix_rtc_fn_method_ffiparticipationmanager_close_slot(ptr) { + const ret = wasm.ubrn_uniffi_matrix_rtc_fn_method_ffiparticipationmanager_close_slot(ptr); + return BigInt.asUintN(64, ret); +} + +/** + * @param {bigint} ptr + * @param {RustCallStatus} f_status_ + * @returns {Uint8Array} + */ +export function ubrn_uniffi_matrix_rtc_fn_method_ffiparticipationmanager_connection_problems(ptr, f_status_) { + _assertClass(f_status_, RustCallStatus); + const ret = wasm.ubrn_uniffi_matrix_rtc_fn_method_ffiparticipationmanager_connection_problems(ptr, f_status_.__wbg_ptr); + var v1 = getArrayU8FromWasm0(ret[0], ret[1]).slice(); + wasm.__wbindgen_free(ret[0], ret[1] * 1, 1); + return v1; +} + +/** + * @param {bigint} ptr + * @param {RustCallStatus} f_status_ + * @returns {Uint8Array} + */ +export function ubrn_uniffi_matrix_rtc_fn_method_ffiparticipationmanager_connections(ptr, f_status_) { + _assertClass(f_status_, RustCallStatus); + const ret = wasm.ubrn_uniffi_matrix_rtc_fn_method_ffiparticipationmanager_connections(ptr, f_status_.__wbg_ptr); + var v1 = getArrayU8FromWasm0(ret[0], ret[1]).slice(); + wasm.__wbindgen_free(ret[0], ret[1] * 1, 1); + return v1; +} + +/** + * @param {bigint} ptr + * @param {RustCallStatus} f_status_ + * @returns {Uint8Array} + */ +export function ubrn_uniffi_matrix_rtc_fn_method_ffiparticipationmanager_debug_snapshot(ptr, f_status_) { + _assertClass(f_status_, RustCallStatus); + const ret = wasm.ubrn_uniffi_matrix_rtc_fn_method_ffiparticipationmanager_debug_snapshot(ptr, f_status_.__wbg_ptr); + var v1 = getArrayU8FromWasm0(ret[0], ret[1]).slice(); + wasm.__wbindgen_free(ret[0], ret[1] * 1, 1); + return v1; +} + +/** + * @param {bigint} ptr + * @param {RustCallStatus} f_status_ + * @returns {number} + */ +export function ubrn_uniffi_matrix_rtc_fn_method_ffiparticipationmanager_is_homeserver_connected(ptr, f_status_) { + _assertClass(f_status_, RustCallStatus); + const ret = wasm.ubrn_uniffi_matrix_rtc_fn_method_ffiparticipationmanager_is_homeserver_connected(ptr, f_status_.__wbg_ptr); + return ret; +} + +/** + * @param {bigint} ptr + * @param {Uint8Array} intent + * @param {Uint8Array} params + * @returns {bigint} + */ +export function ubrn_uniffi_matrix_rtc_fn_method_ffiparticipationmanager_join(ptr, intent, params) { + const ptr0 = passArray8ToWasm0(intent, wasm.__wbindgen_malloc); + const len0 = WASM_VECTOR_LEN; + const ptr1 = passArray8ToWasm0(params, wasm.__wbindgen_malloc); + const len1 = WASM_VECTOR_LEN; + const ret = wasm.ubrn_uniffi_matrix_rtc_fn_method_ffiparticipationmanager_join(ptr, ptr0, len0, ptr1, len1); + return BigInt.asUintN(64, ret); +} + +/** + * @param {bigint} ptr + * @param {RustCallStatus} f_status_ + * @returns {Uint8Array} + */ +export function ubrn_uniffi_matrix_rtc_fn_method_ffiparticipationmanager_key_map(ptr, f_status_) { + _assertClass(f_status_, RustCallStatus); + const ret = wasm.ubrn_uniffi_matrix_rtc_fn_method_ffiparticipationmanager_key_map(ptr, f_status_.__wbg_ptr); + var v1 = getArrayU8FromWasm0(ret[0], ret[1]).slice(); + wasm.__wbindgen_free(ret[0], ret[1] * 1, 1); + return v1; +} + +/** + * @param {bigint} ptr + * @param {Uint8Array} code + * @param {Uint8Array} reason + * @returns {bigint} + */ +export function ubrn_uniffi_matrix_rtc_fn_method_ffiparticipationmanager_leave(ptr, code, reason) { + const ptr0 = passArray8ToWasm0(code, wasm.__wbindgen_malloc); + const len0 = WASM_VECTOR_LEN; + const ptr1 = passArray8ToWasm0(reason, wasm.__wbindgen_malloc); + const len1 = WASM_VECTOR_LEN; + const ret = wasm.ubrn_uniffi_matrix_rtc_fn_method_ffiparticipationmanager_leave(ptr, ptr0, len0, ptr1, len1); + return BigInt.asUintN(64, ret); +} + +/** + * @param {bigint} handle + * @param {RustCallStatus} f_status_ + * @returns {bigint} + */ +export function ubrn_uniffi_matrix_rtc_fn_clone_connectivitysink(handle, f_status_) { + _assertClass(f_status_, RustCallStatus); + const ret = wasm.ubrn_uniffi_matrix_rtc_fn_clone_connectivitysink(handle, f_status_.__wbg_ptr); + return BigInt.asUintN(64, ret); +} + +/** + * @param {bigint} handle + * @param {RustCallStatus} f_status_ + */ +export function ubrn_uniffi_matrix_rtc_fn_free_connectivitysink(handle, f_status_) { + _assertClass(f_status_, RustCallStatus); + wasm.ubrn_uniffi_matrix_rtc_fn_free_connectivitysink(handle, f_status_.__wbg_ptr); +} + +/** + * @param {bigint} ptr + * @param {number} connected + * @param {RustCallStatus} f_status_ + * @returns {number} + */ +export function ubrn_uniffi_matrix_rtc_fn_method_connectivitysink_emit(ptr, connected, f_status_) { + _assertClass(f_status_, RustCallStatus); + const ret = wasm.ubrn_uniffi_matrix_rtc_fn_method_connectivitysink_emit(ptr, connected, f_status_.__wbg_ptr); + return ret; +} + +/** + * @param {bigint} handle + * @param {RustCallStatus} f_status_ + * @returns {bigint} + */ +export function ubrn_uniffi_matrix_rtc_fn_clone_ffimatrixdriver(handle, f_status_) { + _assertClass(f_status_, RustCallStatus); + const ret = wasm.ubrn_uniffi_matrix_rtc_fn_clone_ffimatrixdriver(handle, f_status_.__wbg_ptr); + return BigInt.asUintN(64, ret); +} + +/** + * @param {bigint} handle + * @param {RustCallStatus} f_status_ + */ +export function ubrn_uniffi_matrix_rtc_fn_free_ffimatrixdriver(handle, f_status_) { + _assertClass(f_status_, RustCallStatus); + wasm.ubrn_uniffi_matrix_rtc_fn_free_ffimatrixdriver(handle, f_status_.__wbg_ptr); +} + +/** + * @param {bigint} callback + * @param {RustCallStatus} f_status_ + * @returns {bigint} + */ +export function ubrn_uniffi_matrix_rtc_fn_constructor_ffimatrixdriver_new(callback, f_status_) { + _assertClass(f_status_, RustCallStatus); + const ret = wasm.ubrn_uniffi_matrix_rtc_fn_constructor_ffimatrixdriver_new(callback, f_status_.__wbg_ptr); + return BigInt.asUintN(64, ret); +} + +/** + * @param {bigint} handle + * @param {RustCallStatus} f_status_ + * @returns {bigint} + */ +export function ubrn_uniffi_matrix_rtc_fn_clone_ffiparticipationmanager(handle, f_status_) { + _assertClass(f_status_, RustCallStatus); + const ret = wasm.ubrn_uniffi_matrix_rtc_fn_clone_ffiparticipationmanager(handle, f_status_.__wbg_ptr); + return BigInt.asUintN(64, ret); +} + +/** + * @param {bigint} handle + * @param {RustCallStatus} f_status_ + */ +export function ubrn_uniffi_matrix_rtc_fn_free_ffiparticipationmanager(handle, f_status_) { + _assertClass(f_status_, RustCallStatus); + wasm.ubrn_uniffi_matrix_rtc_fn_free_ffiparticipationmanager(handle, f_status_.__wbg_ptr); +} + +function __wbg_adapter_24(arg0, arg1) { + wasm._dyn_core_e48f7a02345547b9___ops__function__FnMut_____Output______as_wasm_bindgen_65e498d0bf4959ae___closure__WasmClosure___describe__invoke______(arg0, arg1); +} + +function __wbg_adapter_27(arg0, arg1, arg2) { + wasm.closure531_externref_shim(arg0, arg1, arg2); +} + +const ForeignFutureCompleteF32Finalization = (typeof FinalizationRegistry === 'undefined') + ? { register: () => {}, unregister: () => {} } + : new FinalizationRegistry(ptr => wasm.__wbg_foreignfuturecompletef32_free(ptr >>> 0, 1)); + +export class ForeignFutureCompleteF32 { + + __destroy_into_raw() { + const ptr = this.__wbg_ptr; + this.__wbg_ptr = 0; + ForeignFutureCompleteF32Finalization.unregister(this); + return ptr; + } + + free() { + const ptr = this.__destroy_into_raw(); + wasm.__wbg_foreignfuturecompletef32_free(ptr, 0); + } + /** + * @param {ForeignFutureCompleteF32} _ctx + * @param {bigint} callback_data + * @param {any} result + */ + call(_ctx, callback_data, result) { + _assertClass(_ctx, ForeignFutureCompleteF32); + wasm.foreignfuturecompletef32_call(this.__wbg_ptr, _ctx.__wbg_ptr, callback_data, result); + } +} + +const ForeignFutureCompleteF64Finalization = (typeof FinalizationRegistry === 'undefined') + ? { register: () => {}, unregister: () => {} } + : new FinalizationRegistry(ptr => wasm.__wbg_foreignfuturecompletef64_free(ptr >>> 0, 1)); + +export class ForeignFutureCompleteF64 { + + __destroy_into_raw() { + const ptr = this.__wbg_ptr; + this.__wbg_ptr = 0; + ForeignFutureCompleteF64Finalization.unregister(this); + return ptr; + } + + free() { + const ptr = this.__destroy_into_raw(); + wasm.__wbg_foreignfuturecompletef64_free(ptr, 0); + } + /** + * @param {ForeignFutureCompleteF64} _ctx + * @param {bigint} callback_data + * @param {any} result + */ + call(_ctx, callback_data, result) { + _assertClass(_ctx, ForeignFutureCompleteF64); + wasm.foreignfuturecompletef64_call(this.__wbg_ptr, _ctx.__wbg_ptr, callback_data, result); + } +} + +const ForeignFutureCompleteI16Finalization = (typeof FinalizationRegistry === 'undefined') + ? { register: () => {}, unregister: () => {} } + : new FinalizationRegistry(ptr => wasm.__wbg_foreignfuturecompletei16_free(ptr >>> 0, 1)); + +export class ForeignFutureCompleteI16 { + + __destroy_into_raw() { + const ptr = this.__wbg_ptr; + this.__wbg_ptr = 0; + ForeignFutureCompleteI16Finalization.unregister(this); + return ptr; + } + + free() { + const ptr = this.__destroy_into_raw(); + wasm.__wbg_foreignfuturecompletei16_free(ptr, 0); + } + /** + * @param {ForeignFutureCompleteI16} _ctx + * @param {bigint} callback_data + * @param {any} result + */ + call(_ctx, callback_data, result) { + _assertClass(_ctx, ForeignFutureCompleteI16); + wasm.foreignfuturecompletei16_call(this.__wbg_ptr, _ctx.__wbg_ptr, callback_data, result); + } +} + +const ForeignFutureCompleteI32Finalization = (typeof FinalizationRegistry === 'undefined') + ? { register: () => {}, unregister: () => {} } + : new FinalizationRegistry(ptr => wasm.__wbg_foreignfuturecompletei32_free(ptr >>> 0, 1)); + +export class ForeignFutureCompleteI32 { + + __destroy_into_raw() { + const ptr = this.__wbg_ptr; + this.__wbg_ptr = 0; + ForeignFutureCompleteI32Finalization.unregister(this); + return ptr; + } + + free() { + const ptr = this.__destroy_into_raw(); + wasm.__wbg_foreignfuturecompletei32_free(ptr, 0); + } + /** + * @param {ForeignFutureCompleteI32} _ctx + * @param {bigint} callback_data + * @param {any} result + */ + call(_ctx, callback_data, result) { + _assertClass(_ctx, ForeignFutureCompleteI32); + wasm.foreignfuturecompletei32_call(this.__wbg_ptr, _ctx.__wbg_ptr, callback_data, result); + } +} + +const ForeignFutureCompleteI64Finalization = (typeof FinalizationRegistry === 'undefined') + ? { register: () => {}, unregister: () => {} } + : new FinalizationRegistry(ptr => wasm.__wbg_foreignfuturecompletei64_free(ptr >>> 0, 1)); + +export class ForeignFutureCompleteI64 { + + __destroy_into_raw() { + const ptr = this.__wbg_ptr; + this.__wbg_ptr = 0; + ForeignFutureCompleteI64Finalization.unregister(this); + return ptr; + } + + free() { + const ptr = this.__destroy_into_raw(); + wasm.__wbg_foreignfuturecompletei64_free(ptr, 0); + } + /** + * @param {ForeignFutureCompleteI64} _ctx + * @param {bigint} callback_data + * @param {any} result + */ + call(_ctx, callback_data, result) { + _assertClass(_ctx, ForeignFutureCompleteI64); + wasm.foreignfuturecompletei64_call(this.__wbg_ptr, _ctx.__wbg_ptr, callback_data, result); + } +} + +const ForeignFutureCompleteI8Finalization = (typeof FinalizationRegistry === 'undefined') + ? { register: () => {}, unregister: () => {} } + : new FinalizationRegistry(ptr => wasm.__wbg_foreignfuturecompletei8_free(ptr >>> 0, 1)); + +export class ForeignFutureCompleteI8 { + + __destroy_into_raw() { + const ptr = this.__wbg_ptr; + this.__wbg_ptr = 0; + ForeignFutureCompleteI8Finalization.unregister(this); + return ptr; + } + + free() { + const ptr = this.__destroy_into_raw(); + wasm.__wbg_foreignfuturecompletei8_free(ptr, 0); + } + /** + * @param {ForeignFutureCompleteI8} _ctx + * @param {bigint} callback_data + * @param {any} result + */ + call(_ctx, callback_data, result) { + _assertClass(_ctx, ForeignFutureCompleteI8); + wasm.foreignfuturecompletei8_call(this.__wbg_ptr, _ctx.__wbg_ptr, callback_data, result); + } +} + +const ForeignFutureCompleteRustBufferFinalization = (typeof FinalizationRegistry === 'undefined') + ? { register: () => {}, unregister: () => {} } + : new FinalizationRegistry(ptr => wasm.__wbg_foreignfuturecompleterustbuffer_free(ptr >>> 0, 1)); + +export class ForeignFutureCompleteRustBuffer { + + static __wrap(ptr) { + ptr = ptr >>> 0; + const obj = Object.create(ForeignFutureCompleteRustBuffer.prototype); + obj.__wbg_ptr = ptr; + ForeignFutureCompleteRustBufferFinalization.register(obj, obj.__wbg_ptr, obj); + return obj; + } + + __destroy_into_raw() { + const ptr = this.__wbg_ptr; + this.__wbg_ptr = 0; + ForeignFutureCompleteRustBufferFinalization.unregister(this); + return ptr; + } + + free() { + const ptr = this.__destroy_into_raw(); + wasm.__wbg_foreignfuturecompleterustbuffer_free(ptr, 0); + } + /** + * @param {ForeignFutureCompleteRustBuffer} _ctx + * @param {bigint} callback_data + * @param {any} result + */ + call(_ctx, callback_data, result) { + _assertClass(_ctx, ForeignFutureCompleteRustBuffer); + wasm.foreignfuturecompleterustbuffer_call(this.__wbg_ptr, _ctx.__wbg_ptr, callback_data, result); + } +} + +const ForeignFutureCompleteU16Finalization = (typeof FinalizationRegistry === 'undefined') + ? { register: () => {}, unregister: () => {} } + : new FinalizationRegistry(ptr => wasm.__wbg_foreignfuturecompleteu16_free(ptr >>> 0, 1)); + +export class ForeignFutureCompleteU16 { + + __destroy_into_raw() { + const ptr = this.__wbg_ptr; + this.__wbg_ptr = 0; + ForeignFutureCompleteU16Finalization.unregister(this); + return ptr; + } + + free() { + const ptr = this.__destroy_into_raw(); + wasm.__wbg_foreignfuturecompleteu16_free(ptr, 0); + } + /** + * @param {ForeignFutureCompleteU16} _ctx + * @param {bigint} callback_data + * @param {any} result + */ + call(_ctx, callback_data, result) { + _assertClass(_ctx, ForeignFutureCompleteU16); + wasm.foreignfuturecompleteu16_call(this.__wbg_ptr, _ctx.__wbg_ptr, callback_data, result); + } +} + +const ForeignFutureCompleteU32Finalization = (typeof FinalizationRegistry === 'undefined') + ? { register: () => {}, unregister: () => {} } + : new FinalizationRegistry(ptr => wasm.__wbg_foreignfuturecompleteu32_free(ptr >>> 0, 1)); + +export class ForeignFutureCompleteU32 { + + __destroy_into_raw() { + const ptr = this.__wbg_ptr; + this.__wbg_ptr = 0; + ForeignFutureCompleteU32Finalization.unregister(this); + return ptr; + } + + free() { + const ptr = this.__destroy_into_raw(); + wasm.__wbg_foreignfuturecompleteu32_free(ptr, 0); + } + /** + * @param {ForeignFutureCompleteU32} _ctx + * @param {bigint} callback_data + * @param {any} result + */ + call(_ctx, callback_data, result) { + _assertClass(_ctx, ForeignFutureCompleteU32); + wasm.foreignfuturecompleteu32_call(this.__wbg_ptr, _ctx.__wbg_ptr, callback_data, result); + } +} + +const ForeignFutureCompleteU64Finalization = (typeof FinalizationRegistry === 'undefined') + ? { register: () => {}, unregister: () => {} } + : new FinalizationRegistry(ptr => wasm.__wbg_foreignfuturecompleteu64_free(ptr >>> 0, 1)); + +export class ForeignFutureCompleteU64 { + + __destroy_into_raw() { + const ptr = this.__wbg_ptr; + this.__wbg_ptr = 0; + ForeignFutureCompleteU64Finalization.unregister(this); + return ptr; + } + + free() { + const ptr = this.__destroy_into_raw(); + wasm.__wbg_foreignfuturecompleteu64_free(ptr, 0); + } + /** + * @param {ForeignFutureCompleteU64} _ctx + * @param {bigint} callback_data + * @param {any} result + */ + call(_ctx, callback_data, result) { + _assertClass(_ctx, ForeignFutureCompleteU64); + wasm.foreignfuturecompleteu64_call(this.__wbg_ptr, _ctx.__wbg_ptr, callback_data, result); + } +} + +const ForeignFutureCompleteU8Finalization = (typeof FinalizationRegistry === 'undefined') + ? { register: () => {}, unregister: () => {} } + : new FinalizationRegistry(ptr => wasm.__wbg_foreignfuturecompleteu8_free(ptr >>> 0, 1)); + +export class ForeignFutureCompleteU8 { + + __destroy_into_raw() { + const ptr = this.__wbg_ptr; + this.__wbg_ptr = 0; + ForeignFutureCompleteU8Finalization.unregister(this); + return ptr; + } + + free() { + const ptr = this.__destroy_into_raw(); + wasm.__wbg_foreignfuturecompleteu8_free(ptr, 0); + } + /** + * @param {ForeignFutureCompleteU8} _ctx + * @param {bigint} callback_data + * @param {any} result + */ + call(_ctx, callback_data, result) { + _assertClass(_ctx, ForeignFutureCompleteU8); + wasm.foreignfuturecompleteu8_call(this.__wbg_ptr, _ctx.__wbg_ptr, callback_data, result); + } +} + +const ForeignFutureCompleteVoidFinalization = (typeof FinalizationRegistry === 'undefined') + ? { register: () => {}, unregister: () => {} } + : new FinalizationRegistry(ptr => wasm.__wbg_foreignfuturecompletevoid_free(ptr >>> 0, 1)); + +export class ForeignFutureCompleteVoid { + + static __wrap(ptr) { + ptr = ptr >>> 0; + const obj = Object.create(ForeignFutureCompleteVoid.prototype); + obj.__wbg_ptr = ptr; + ForeignFutureCompleteVoidFinalization.register(obj, obj.__wbg_ptr, obj); + return obj; + } + + __destroy_into_raw() { + const ptr = this.__wbg_ptr; + this.__wbg_ptr = 0; + ForeignFutureCompleteVoidFinalization.unregister(this); + return ptr; + } + + free() { + const ptr = this.__destroy_into_raw(); + wasm.__wbg_foreignfuturecompletevoid_free(ptr, 0); + } + /** + * @param {ForeignFutureCompleteVoid} _ctx + * @param {bigint} callback_data + * @param {any} result + */ + call(_ctx, callback_data, result) { + _assertClass(_ctx, ForeignFutureCompleteVoid); + wasm.foreignfuturecompletevoid_call(this.__wbg_ptr, _ctx.__wbg_ptr, callback_data, result); + } +} + +const RustCallStatusFinalization = (typeof FinalizationRegistry === 'undefined') + ? { register: () => {}, unregister: () => {} } + : new FinalizationRegistry(ptr => wasm.__wbg_rustcallstatus_free(ptr >>> 0, 1)); + +export class RustCallStatus { + + __destroy_into_raw() { + const ptr = this.__wbg_ptr; + this.__wbg_ptr = 0; + RustCallStatusFinalization.unregister(this); + return ptr; + } + + free() { + const ptr = this.__destroy_into_raw(); + wasm.__wbg_rustcallstatus_free(ptr, 0); + } + /** + * @returns {number} + */ + get code() { + const ret = wasm.__wbg_get_rustcallstatus_code(this.__wbg_ptr); + return ret; + } + /** + * @param {number} arg0 + */ + set code(arg0) { + wasm.__wbg_set_rustcallstatus_code(this.__wbg_ptr, arg0); + } + /** + * @param {Uint8Array | null} [bytes] + */ + set errorBuf(bytes) { + var ptr0 = isLikeNone(bytes) ? 0 : passArray8ToWasm0(bytes, wasm.__wbindgen_malloc); + var len0 = WASM_VECTOR_LEN; + wasm.rustcallstatus_set_error_buf(this.__wbg_ptr, ptr0, len0); + } + constructor() { + const ret = wasm.rustcallstatus_new(); + this.__wbg_ptr = ret >>> 0; + RustCallStatusFinalization.register(this, this.__wbg_ptr, this); + return this; + } + /** + * @returns {Uint8Array | undefined} + */ + get errorBuf() { + const ptr = this.__destroy_into_raw(); + const ret = wasm.rustcallstatus_error_buf(ptr); + let v1; + if (ret[0] !== 0) { + v1 = getArrayU8FromWasm0(ret[0], ret[1]).slice(); + wasm.__wbindgen_free(ret[0], ret[1] * 1, 1); + } + return v1; + } +} + +async function __wbg_load(module, imports) { + if (typeof Response === 'function' && module instanceof Response) { + if (typeof WebAssembly.instantiateStreaming === 'function') { + try { + return await WebAssembly.instantiateStreaming(module, imports); + + } catch (e) { + if (module.headers.get('Content-Type') != 'application/wasm') { + console.warn("`WebAssembly.instantiateStreaming` failed because your server does not serve Wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n", e); + + } else { + throw e; + } + } + } + + const bytes = await module.arrayBuffer(); + return await WebAssembly.instantiate(bytes, imports); + + } else { + const instance = await WebAssembly.instantiate(module, imports); + + if (instance instanceof WebAssembly.Instance) { + return { instance, module }; + + } else { + return instance; + } + } +} + +function __wbg_get_imports() { + const imports = {}; + imports.wbg = {}; + imports.wbg.__wbg_buffer_609cc3eee51ed158 = function(arg0) { + const ret = arg0.buffer; + return ret; + }; + imports.wbg.__wbg_call_0056921d632def66 = function(arg0, arg1, arg2) { + const ret = arg0.call(arg1, BigInt.asUintN(64, arg2)); + return ret; + }; + imports.wbg.__wbg_call_00ed0f3262ca10fc = function(arg0, arg1, arg2) { + const ret = arg0.call(arg1, BigInt.asUintN(64, arg2)); + return ret; + }; + imports.wbg.__wbg_call_02529374d31ad97c = function(arg0, arg1, arg2) { + arg0.call(arg1, BigInt.asUintN(64, arg2)); + }; + imports.wbg.__wbg_call_0433755a93443d6e = function(arg0, arg1, arg2, arg3) { + const ret = arg0.call(arg1, BigInt.asUintN(64, arg2), BigInt.asUintN(64, arg3)); + return ret; + }; + imports.wbg.__wbg_call_05dc34bdb8662702 = function(arg0, arg1, arg2, arg3) { + const ret = arg0.call(arg1, BigInt.asUintN(64, arg2), BigInt.asUintN(64, arg3)); + return ret; + }; + imports.wbg.__wbg_call_0ba4077697ab1405 = function(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10) { + var v0 = getArrayU8FromWasm0(arg3, arg4).slice(); + wasm.__wbindgen_free(arg3, arg4 * 1, 1); + var v1 = getArrayU8FromWasm0(arg5, arg6).slice(); + wasm.__wbindgen_free(arg5, arg6 * 1, 1); + var v2 = getArrayU8FromWasm0(arg7, arg8).slice(); + wasm.__wbindgen_free(arg7, arg8 * 1, 1); + const ret = arg0.call(arg1, BigInt.asUintN(64, arg2), v0, v1, v2, ForeignFutureCompleteRustBuffer.__wrap(arg9), BigInt.asUintN(64, arg10)); + return ret; + }; + imports.wbg.__wbg_call_21960420ca81bc05 = function(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12) { + var v0 = getArrayU8FromWasm0(arg3, arg4).slice(); + wasm.__wbindgen_free(arg3, arg4 * 1, 1); + var v1 = getArrayU8FromWasm0(arg5, arg6).slice(); + wasm.__wbindgen_free(arg5, arg6 * 1, 1); + var v2 = getArrayU8FromWasm0(arg7, arg8).slice(); + wasm.__wbindgen_free(arg7, arg8 * 1, 1); + var v3 = getArrayU8FromWasm0(arg9, arg10).slice(); + wasm.__wbindgen_free(arg9, arg10 * 1, 1); + const ret = arg0.call(arg1, BigInt.asUintN(64, arg2), v0, v1, v2, v3, ForeignFutureCompleteRustBuffer.__wrap(arg11), BigInt.asUintN(64, arg12)); + return ret; + }; + imports.wbg.__wbg_call_2798409ff618ef7d = function(arg0, arg1, arg2) { + arg0.call(arg1, BigInt.asUintN(64, arg2)); + }; + imports.wbg.__wbg_call_2f24f710f0dd8d10 = function(arg0, arg1, arg2, arg3, arg4, arg5, arg6) { + var v0 = getArrayU8FromWasm0(arg3, arg4).slice(); + wasm.__wbindgen_free(arg3, arg4 * 1, 1); + var v1 = getArrayU8FromWasm0(arg5, arg6).slice(); + wasm.__wbindgen_free(arg5, arg6 * 1, 1); + const ret = arg0.call(arg1, BigInt.asUintN(64, arg2), v0, v1); + return ret; + }; + imports.wbg.__wbg_call_4022622bc30aaf84 = function(arg0, arg1, arg2) { + arg0.call(arg1, BigInt.asUintN(64, arg2)); + }; + imports.wbg.__wbg_call_45ca295cb4469524 = function(arg0, arg1, arg2, arg3) { + arg0.call(arg1, BigInt.asUintN(64, arg2), arg3); + }; + imports.wbg.__wbg_call_45f35e4128d6c004 = function(arg0, arg1, arg2, arg3, arg4, arg5, arg6) { + var v0 = getArrayU8FromWasm0(arg3, arg4).slice(); + wasm.__wbindgen_free(arg3, arg4 * 1, 1); + const ret = arg0.call(arg1, BigInt.asUintN(64, arg2), v0, ForeignFutureCompleteRustBuffer.__wrap(arg5), BigInt.asUintN(64, arg6)); + return ret; + }; + imports.wbg.__wbg_call_4614c0a573de577f = function(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13) { + var v0 = getArrayU8FromWasm0(arg3, arg4).slice(); + wasm.__wbindgen_free(arg3, arg4 * 1, 1); + var v1 = getArrayU8FromWasm0(arg5, arg6).slice(); + wasm.__wbindgen_free(arg5, arg6 * 1, 1); + var v2 = getArrayU8FromWasm0(arg7, arg8).slice(); + wasm.__wbindgen_free(arg7, arg8 * 1, 1); + var v3 = getArrayU8FromWasm0(arg9, arg10).slice(); + wasm.__wbindgen_free(arg9, arg10 * 1, 1); + const ret = arg0.call(arg1, BigInt.asUintN(64, arg2), v0, v1, v2, v3, BigInt.asUintN(64, arg11), ForeignFutureCompleteRustBuffer.__wrap(arg12), BigInt.asUintN(64, arg13)); + return ret; + }; + imports.wbg.__wbg_call_496b92421c092b65 = function(arg0, arg1, arg2) { + const ret = arg0.call(arg1, BigInt.asUintN(64, arg2)); + return ret; + }; + imports.wbg.__wbg_call_571d4611879307e7 = function(arg0, arg1, arg2, arg3) { + const ret = arg0.call(arg1, BigInt.asUintN(64, arg2), BigInt.asUintN(64, arg3)); + return ret; + }; + imports.wbg.__wbg_call_65221d24e12159bf = function(arg0, arg1, arg2, arg3, arg4) { + const ret = arg0.call(arg1, BigInt.asUintN(64, arg2), ForeignFutureCompleteRustBuffer.__wrap(arg3), BigInt.asUintN(64, arg4)); + return ret; + }; + imports.wbg.__wbg_call_65360e4d1b0f41fa = function(arg0, arg1, arg2) { + arg0.call(arg1, BigInt.asUintN(64, arg2)); + }; + imports.wbg.__wbg_call_672a4d21634d4a24 = function() { return handleError(function (arg0, arg1) { + const ret = arg0.call(arg1); + return ret; + }, arguments) }; + imports.wbg.__wbg_call_67bcb4b184601516 = function(arg0, arg1, arg2) { + arg0.call(arg1, BigInt.asUintN(64, arg2)); + }; + imports.wbg.__wbg_call_79e16370d6861b4f = function(arg0, arg1, arg2, arg3, arg4) { + var v0 = getArrayU8FromWasm0(arg3, arg4).slice(); + wasm.__wbindgen_free(arg3, arg4 * 1, 1); + const ret = arg0.call(arg1, BigInt.asUintN(64, arg2), v0); + return ret; + }; + imports.wbg.__wbg_call_7cccdd69e0791ae2 = function() { return handleError(function (arg0, arg1, arg2) { + const ret = arg0.call(arg1, arg2); + return ret; + }, arguments) }; + imports.wbg.__wbg_call_85dc743acd81f8e1 = function(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15) { + var v0 = getArrayU8FromWasm0(arg3, arg4).slice(); + wasm.__wbindgen_free(arg3, arg4 * 1, 1); + var v1 = getArrayU8FromWasm0(arg5, arg6).slice(); + wasm.__wbindgen_free(arg5, arg6 * 1, 1); + var v2 = getArrayU8FromWasm0(arg7, arg8).slice(); + wasm.__wbindgen_free(arg7, arg8 * 1, 1); + var v3 = getArrayU8FromWasm0(arg9, arg10).slice(); + wasm.__wbindgen_free(arg9, arg10 * 1, 1); + var v4 = getArrayU8FromWasm0(arg11, arg12).slice(); + wasm.__wbindgen_free(arg11, arg12 * 1, 1); + const ret = arg0.call(arg1, BigInt.asUintN(64, arg2), v0, v1, v2, v3, v4, BigInt.asUintN(64, arg13), ForeignFutureCompleteVoid.__wrap(arg14), BigInt.asUintN(64, arg15)); + return ret; + }; + imports.wbg.__wbg_call_9a894f10d06a53c9 = function(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) { + var v0 = getArrayU8FromWasm0(arg3, arg4).slice(); + wasm.__wbindgen_free(arg3, arg4 * 1, 1); + var v1 = getArrayU8FromWasm0(arg5, arg6).slice(); + wasm.__wbindgen_free(arg5, arg6 * 1, 1); + const ret = arg0.call(arg1, BigInt.asUintN(64, arg2), v0, v1, ForeignFutureCompleteVoid.__wrap(arg7), BigInt.asUintN(64, arg8)); + return ret; + }; + imports.wbg.__wbg_call_9f7a841426436a44 = function(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) { + var v0 = getArrayU8FromWasm0(arg3, arg4).slice(); + wasm.__wbindgen_free(arg3, arg4 * 1, 1); + var v1 = getArrayU8FromWasm0(arg5, arg6).slice(); + wasm.__wbindgen_free(arg5, arg6 * 1, 1); + const ret = arg0.call(arg1, BigInt.asUintN(64, arg2), v0, v1, ForeignFutureCompleteVoid.__wrap(arg7), BigInt.asUintN(64, arg8)); + return ret; + }; + imports.wbg.__wbg_call_a6145cafbb6c59f0 = function(arg0, arg1, arg2) { + arg0.call(arg1, BigInt.asUintN(64, arg2)); + }; + imports.wbg.__wbg_call_a79f116fab0f1a0a = function(arg0, arg1, arg2, arg3, arg4, arg5, arg6) { + var v0 = getArrayU8FromWasm0(arg3, arg4).slice(); + wasm.__wbindgen_free(arg3, arg4 * 1, 1); + var v1 = getArrayU8FromWasm0(arg5, arg6).slice(); + wasm.__wbindgen_free(arg5, arg6 * 1, 1); + const ret = arg0.call(arg1, BigInt.asUintN(64, arg2), v0, v1); + return ret; + }; + imports.wbg.__wbg_call_abeb9928262c69b8 = function(arg0, arg1, arg2, arg3, arg4) { + var v0 = getArrayU8FromWasm0(arg3, arg4).slice(); + wasm.__wbindgen_free(arg3, arg4 * 1, 1); + const ret = arg0.call(arg1, BigInt.asUintN(64, arg2), v0); + return ret; + }; + imports.wbg.__wbg_call_b66d526ecf55c81d = function(arg0, arg1, arg2) { + const ret = arg0.call(arg1, BigInt.asUintN(64, arg2)); + return ret; + }; + imports.wbg.__wbg_call_bd883beab9425b7c = function(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9) { + var v0 = getArrayU8FromWasm0(arg3, arg4).slice(); + wasm.__wbindgen_free(arg3, arg4 * 1, 1); + var v1 = getArrayU8FromWasm0(arg5, arg6).slice(); + wasm.__wbindgen_free(arg5, arg6 * 1, 1); + const ret = arg0.call(arg1, BigInt.asUintN(64, arg2), v0, v1, arg7 >>> 0, ForeignFutureCompleteRustBuffer.__wrap(arg8), BigInt.asUintN(64, arg9)); + return ret; + }; + imports.wbg.__wbg_call_c9c4e766b640b52d = function(arg0, arg1, arg2, arg3) { + const ret = arg0.call(arg1, BigInt.asUintN(64, arg2), BigInt.asUintN(64, arg3)); + return ret; + }; + imports.wbg.__wbg_call_ca06027b14b17766 = function(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13) { + var v0 = getArrayU8FromWasm0(arg3, arg4).slice(); + wasm.__wbindgen_free(arg3, arg4 * 1, 1); + var v1 = getArrayU8FromWasm0(arg5, arg6).slice(); + wasm.__wbindgen_free(arg5, arg6 * 1, 1); + var v2 = getArrayU8FromWasm0(arg7, arg8).slice(); + wasm.__wbindgen_free(arg7, arg8 * 1, 1); + var v3 = getArrayU8FromWasm0(arg10, arg11).slice(); + wasm.__wbindgen_free(arg10, arg11 * 1, 1); + const ret = arg0.call(arg1, BigInt.asUintN(64, arg2), v0, v1, v2, BigInt.asUintN(64, arg9), v3, ForeignFutureCompleteRustBuffer.__wrap(arg12), BigInt.asUintN(64, arg13)); + return ret; + }; + imports.wbg.__wbg_call_db19d6a7a08fbd37 = function(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11) { + var v0 = getArrayU8FromWasm0(arg3, arg4).slice(); + wasm.__wbindgen_free(arg3, arg4 * 1, 1); + var v1 = getArrayU8FromWasm0(arg5, arg6).slice(); + wasm.__wbindgen_free(arg5, arg6 * 1, 1); + var v2 = getArrayU8FromWasm0(arg7, arg8).slice(); + wasm.__wbindgen_free(arg7, arg8 * 1, 1); + const ret = arg0.call(arg1, BigInt.asUintN(64, arg2), v0, v1, v2, BigInt.asUintN(64, arg9), ForeignFutureCompleteRustBuffer.__wrap(arg10), BigInt.asUintN(64, arg11)); + return ret; + }; + imports.wbg.__wbg_call_dd8fc90cc1eed1a0 = function(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) { + var v0 = getArrayU8FromWasm0(arg3, arg4).slice(); + wasm.__wbindgen_free(arg3, arg4 * 1, 1); + var v1 = getArrayU8FromWasm0(arg5, arg6).slice(); + wasm.__wbindgen_free(arg5, arg6 * 1, 1); + const ret = arg0.call(arg1, BigInt.asUintN(64, arg2), v0, v1, ForeignFutureCompleteRustBuffer.__wrap(arg7), BigInt.asUintN(64, arg8)); + return ret; + }; + imports.wbg.__wbg_call_df53672c5883e9e7 = function(arg0, arg1, arg2, arg3, arg4) { + var v0 = getArrayU8FromWasm0(arg3, arg4).slice(); + wasm.__wbindgen_free(arg3, arg4 * 1, 1); + const ret = arg0.call(arg1, BigInt.asUintN(64, arg2), v0); + return ret; + }; + imports.wbg.__wbg_call_f95ee156aae25631 = function(arg0, arg1, arg2) { + const ret = arg0.call(arg1, BigInt.asUintN(64, arg2)); + return ret; + }; + imports.wbg.__wbg_call_fb7f89f8d567b160 = function(arg0, arg1, arg2) { + const ret = arg0.call(arg1, BigInt.asUintN(64, arg2)); + return ret; + }; + imports.wbg.__wbg_call_fedc2bfb0eb6df90 = function(arg0, arg1, arg2) { + arg0.call(arg1, BigInt.asUintN(64, arg2)); + }; + imports.wbg.__wbg_call_ff7e7c3b656ecebf = function(arg0, arg1, arg2) { + const ret = arg0.call(arg1, BigInt.asUintN(64, arg2)); + return ret; + }; + imports.wbg.__wbg_callstatus_ab813cdd9fb59b5c = function(arg0) { + const ret = arg0.call_status; + _assertClass(ret, RustCallStatus); + var ptr1 = ret.__destroy_into_raw(); + return ptr1; + }; + imports.wbg.__wbg_canceldelayedevent_f1442079ae4bb697 = function(arg0) { + const ret = arg0.cancel_delayed_event; + return ret; + }; + imports.wbg.__wbg_clearTimeout_5a54f8841c30079a = function(arg0) { + const ret = clearTimeout(arg0); + return ret; + }; + imports.wbg.__wbg_code_a1790f546af56cdc = function(arg0) { + const ret = arg0.code; + return ret; + }; + imports.wbg.__wbg_code_b18c52258a7d4327 = function(arg0) { + const ret = arg0.code; + return ret; + }; + imports.wbg.__wbg_crypto_86f2631e91b51511 = function(arg0) { + const ret = arg0.crypto; + return ret; + }; + imports.wbg.__wbg_delegatelivekitdelayedleave_991fce363b53064f = function(arg0) { + const ret = arg0.delegate_livekit_delayed_leave; + return ret; + }; + imports.wbg.__wbg_errorbuf_59fafcd45c02f900 = function(arg0, arg1) { + const ret = arg1.errorBuf; + var ptr1 = isLikeNone(ret) ? 0 : passArray8ToWasm0(ret, wasm.__wbindgen_malloc); + var len1 = WASM_VECTOR_LEN; + getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true); + getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true); + }; + imports.wbg.__wbg_errorbuf_9e8687be915296d2 = function(arg0, arg1) { + const ret = arg1.errorBuf; + var ptr1 = isLikeNone(ret) ? 0 : passArray8ToWasm0(ret, wasm.__wbindgen_malloc); + var len1 = WASM_VECTOR_LEN; + getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true); + getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true); + }; + imports.wbg.__wbg_free_b85a6024660bd07c = function(arg0) { + const ret = arg0.free; + return ret; + }; + imports.wbg.__wbg_getRandomValues_b3f15fcbfabb0f8b = function() { return handleError(function (arg0, arg1) { + arg0.getRandomValues(arg1); + }, arguments) }; + imports.wbg.__wbg_getlivekittoken_269ca0b4c594770a = function(arg0) { + const ret = arg0.get_livekit_token; + return ret; + }; + imports.wbg.__wbg_getrtctransports_8be200fadbe143dc = function(arg0) { + const ret = arg0.get_rtc_transports; + return ret; + }; + imports.wbg.__wbg_handle_c2870606e589531b = function(arg0) { + const ret = arg0.handle; + return ret; + }; + imports.wbg.__wbg_ishomeserverconnected_dc5057f7242a591e = function(arg0) { + const ret = arg0.is_homeserver_connected; + return ret; + }; + imports.wbg.__wbg_msCrypto_d562bbe83e0d4b91 = function(arg0) { + const ret = arg0.msCrypto; + return ret; + }; + imports.wbg.__wbg_new_a12002a7f91c75be = function(arg0) { + const ret = new Uint8Array(arg0); + return ret; + }; + imports.wbg.__wbg_newnoargs_105ed471475aaf50 = function(arg0, arg1) { + const ret = new Function(getStringFromWasm0(arg0, arg1)); + return ret; + }; + imports.wbg.__wbg_newwithbyteoffsetandlength_d97e637ebe145a9a = function(arg0, arg1, arg2) { + const ret = new Uint8Array(arg0, arg1 >>> 0, arg2 >>> 0); + return ret; + }; + imports.wbg.__wbg_newwithlength_a381634e90c276d4 = function(arg0) { + const ret = new Uint8Array(arg0 >>> 0); + return ret; + }; + imports.wbg.__wbg_node_e1f24f89a7336c2e = function(arg0) { + const ret = arg0.node; + return ret; + }; + imports.wbg.__wbg_now_807e54c39636c349 = function() { + const ret = Date.now(); + return ret; + }; + imports.wbg.__wbg_onconnectionschange_cb540732b536bde5 = function(arg0) { + const ret = arg0.on_connections_change; + return ret; + }; + imports.wbg.__wbg_onkeymapchange_7af99be63015699f = function(arg0) { + const ret = arg0.on_key_map_change; + return ret; + }; + imports.wbg.__wbg_onkeyrejected_0811c486ecda07ea = function(arg0) { + const ret = arg0.on_key_rejected; + return ret; + }; + imports.wbg.__wbg_onmembershipschange_72a01e47629908a2 = function(arg0) { + const ret = arg0.on_memberships_change; + return ret; + }; + imports.wbg.__wbg_onstatuschange_926e83644f91f32d = function(arg0) { + const ret = arg0.on_status_change; + return ret; + }; + imports.wbg.__wbg_pointee_26637032edb8983c = function(arg0) { + const ret = arg0.pointee; + return isLikeNone(ret) ? 0xFFFFFF : ret; + }; + imports.wbg.__wbg_process_3975fd6c72f520aa = function(arg0) { + const ret = arg0.process; + return ret; + }; + imports.wbg.__wbg_queueMicrotask_97d92b4fcc8a61c5 = function(arg0) { + queueMicrotask(arg0); + }; + imports.wbg.__wbg_queueMicrotask_d3219def82552485 = function(arg0) { + const ret = arg0.queueMicrotask; + return ret; + }; + imports.wbg.__wbg_randomFillSync_f8c153b79f285817 = function() { return handleError(function (arg0, arg1) { + arg0.randomFillSync(arg1); + }, arguments) }; + imports.wbg.__wbg_readevents_98385cdfe47bdeee = function(arg0) { + const ret = arg0.read_events; + return ret; + }; + imports.wbg.__wbg_readstate_a52da7153b66ed2b = function(arg0) { + const ret = arg0.read_state; + return ret; + }; + imports.wbg.__wbg_require_b74f47fc2d022fd6 = function() { return handleError(function () { + const ret = module.require; + return ret; + }, arguments) }; + imports.wbg.__wbg_resolve_4851785c9c5f573d = function(arg0) { + const ret = Promise.resolve(arg0); + return ret; + }; + imports.wbg.__wbg_restartdelayedevent_0d0c2a4a4627841f = function(arg0) { + const ret = arg0.restart_delayed_event; + return ret; + }; + imports.wbg.__wbg_returnvalue_03774948f0205329 = function(arg0) { + const ret = arg0.return_value; + return ret; + }; + imports.wbg.__wbg_returnvalue_21195623004109c3 = function(arg0, arg1) { + const ret = arg1.return_value; + const ptr1 = passArray8ToWasm0(ret, wasm.__wbindgen_malloc); + const len1 = WASM_VECTOR_LEN; + getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true); + getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true); + }; + imports.wbg.__wbg_returnvalue_2620087eeddb8b84 = function(arg0) { + const ret = arg0.return_value; + return ret; + }; + imports.wbg.__wbg_returnvalue_38e0584d82a3ca2e = function(arg0) { + const ret = arg0.return_value; + return ret; + }; + imports.wbg.__wbg_returnvalue_3e9d3c06adc527d8 = function(arg0) { + const ret = arg0.return_value; + return ret; + }; + imports.wbg.__wbg_returnvalue_6e396db732507afb = function(arg0) { + const ret = arg0.return_value; + return ret; + }; + imports.wbg.__wbg_returnvalue_7debfc20c2457c0f = function(arg0) { + const ret = arg0.return_value; + return ret; + }; + imports.wbg.__wbg_returnvalue_92b4f6af41751b5a = function(arg0) { + const ret = arg0.return_value; + return ret; + }; + imports.wbg.__wbg_returnvalue_a10e08181b6e3347 = function(arg0) { + const ret = arg0.return_value; + return ret; + }; + imports.wbg.__wbg_returnvalue_b2583433f7d5bc58 = function(arg0) { + const ret = arg0.return_value; + return ret; + }; + imports.wbg.__wbg_returnvalue_fe6442da8edb6e26 = function(arg0) { + const ret = arg0.return_value; + return ret; + }; + imports.wbg.__wbg_senddelayedevent_1a17e9af52ac70ce = function(arg0) { + const ret = arg0.send_delayed_event; + return ret; + }; + imports.wbg.__wbg_senddelayedstateevent_7310e92bccc3dd9a = function(arg0) { + const ret = arg0.send_delayed_state_event; + return ret; + }; + imports.wbg.__wbg_sendstateevent_b46311c2c989f673 = function(arg0) { + const ret = arg0.send_state_event; + return ret; + }; + imports.wbg.__wbg_sendstickyevent_ae6f44183a0c7825 = function(arg0) { + const ret = arg0.send_sticky_event; + return ret; + }; + imports.wbg.__wbg_sendtodevice_a3e33fb31230ba64 = function(arg0) { + const ret = arg0.send_to_device; + return ret; + }; + imports.wbg.__wbg_setTimeout_db2dbaeefb6f39c7 = function() { return handleError(function (arg0, arg1) { + const ret = setTimeout(arg0, arg1); + return ret; + }, arguments) }; + imports.wbg.__wbg_set_65595bdd868b3009 = function(arg0, arg1, arg2) { + arg0.set(arg1, arg2 >>> 0); + }; + imports.wbg.__wbg_static_accessor_GLOBAL_88a902d13a557d07 = function() { + const ret = typeof global === 'undefined' ? null : global; + return isLikeNone(ret) ? 0 : addToExternrefTable0(ret); + }; + imports.wbg.__wbg_static_accessor_GLOBAL_THIS_56578be7e9f832b0 = function() { + const ret = typeof globalThis === 'undefined' ? null : globalThis; + return isLikeNone(ret) ? 0 : addToExternrefTable0(ret); + }; + imports.wbg.__wbg_static_accessor_SELF_37c5d418e4bf5819 = function() { + const ret = typeof self === 'undefined' ? null : self; + return isLikeNone(ret) ? 0 : addToExternrefTable0(ret); + }; + imports.wbg.__wbg_static_accessor_WINDOW_5de37043a91a9c40 = function() { + const ret = typeof window === 'undefined' ? null : window; + return isLikeNone(ret) ? 0 : addToExternrefTable0(ret); + }; + imports.wbg.__wbg_subarray_aa9065fa9dc5df96 = function(arg0, arg1, arg2) { + const ret = arg0.subarray(arg1 >>> 0, arg2 >>> 0); + return ret; + }; + imports.wbg.__wbg_subscribeconnectivity_a75e094330a03e3e = function(arg0) { + const ret = arg0.subscribe_connectivity; + return ret; + }; + imports.wbg.__wbg_subscriberoomevents_2e4d5ca6372fe4cd = function(arg0) { + const ret = arg0.subscribe_room_events; + return ret; + }; + imports.wbg.__wbg_subscribestateupdates_06939632cde2db00 = function(arg0) { + const ret = arg0.subscribe_state_updates; + return ret; + }; + imports.wbg.__wbg_subscribetodeviceevents_afcc4eb08f3d890c = function(arg0) { + const ret = arg0.subscribe_to_device_events; + return ret; + }; + imports.wbg.__wbg_then_44b73946d2fb3e7d = function(arg0, arg1) { + const ret = arg0.then(arg1); + return ret; + }; + imports.wbg.__wbg_unifficlone_25a64f9a81fb5b28 = function(arg0) { + const ret = arg0.uniffi_clone; + return ret; + }; + imports.wbg.__wbg_unifficlone_6471a1309ee8fc26 = function(arg0) { + const ret = arg0.uniffi_clone; + return ret; + }; + imports.wbg.__wbg_unifficlone_95a28cf009142cf6 = function(arg0) { + const ret = arg0.uniffi_clone; + return ret; + }; + imports.wbg.__wbg_unifficlone_9de5c992227b473d = function(arg0) { + const ret = arg0.uniffi_clone; + return ret; + }; + imports.wbg.__wbg_unifficlone_f4e9653dc2b93c0c = function(arg0) { + const ret = arg0.uniffi_clone; + return ret; + }; + imports.wbg.__wbg_unifficlone_fe0240768db0e3d6 = function(arg0) { + const ret = arg0.uniffi_clone; + return ret; + }; + imports.wbg.__wbg_uniffifree_00c9e670fc140d79 = function(arg0) { + const ret = arg0.uniffi_free; + return ret; + }; + imports.wbg.__wbg_uniffifree_2b26526e84ac127f = function(arg0) { + const ret = arg0.uniffi_free; + return ret; + }; + imports.wbg.__wbg_uniffifree_313a3d469f2be86d = function(arg0) { + const ret = arg0.uniffi_free; + return ret; + }; + imports.wbg.__wbg_uniffifree_7f877a9bb1d1f761 = function(arg0) { + const ret = arg0.uniffi_free; + return ret; + }; + imports.wbg.__wbg_uniffifree_af6c094a1e08186f = function(arg0) { + const ret = arg0.uniffi_free; + return ret; + }; + imports.wbg.__wbg_uniffifree_c315e1fbfd7f9e6a = function(arg0) { + const ret = arg0.uniffi_free; + return ret; + }; + imports.wbg.__wbg_versions_4e31226f5e8dc909 = function(arg0) { + const ret = arg0.versions; + return ret; + }; + imports.wbg.__wbindgen_cb_drop = function(arg0) { + const obj = arg0.original; + if (obj.cnt-- == 1) { + obj.a = 0; + return true; + } + const ret = false; + return ret; + }; + imports.wbg.__wbindgen_closure_wrapper2151 = function(arg0, arg1, arg2) { + const ret = makeMutClosure(arg0, arg1, 520, __wbg_adapter_24); + return ret; + }; + imports.wbg.__wbindgen_closure_wrapper2175 = function(arg0, arg1, arg2) { + const ret = makeMutClosure(arg0, arg1, 532, __wbg_adapter_27); + return ret; + }; + imports.wbg.__wbindgen_init_externref_table = function() { + const table = wasm.__wbindgen_export_3; + const offset = table.grow(4); + table.set(0, undefined); + table.set(offset + 0, undefined); + table.set(offset + 1, null); + table.set(offset + 2, true); + table.set(offset + 3, false); + ; + }; + imports.wbg.__wbindgen_is_function = function(arg0) { + const ret = typeof(arg0) === 'function'; + return ret; + }; + imports.wbg.__wbindgen_is_object = function(arg0) { + const val = arg0; + const ret = typeof(val) === 'object' && val !== null; + return ret; + }; + imports.wbg.__wbindgen_is_string = function(arg0) { + const ret = typeof(arg0) === 'string'; + return ret; + }; + imports.wbg.__wbindgen_is_undefined = function(arg0) { + const ret = arg0 === undefined; + return ret; + }; + imports.wbg.__wbindgen_memory = function() { + const ret = wasm.memory; + return ret; + }; + imports.wbg.__wbindgen_string_new = function(arg0, arg1) { + const ret = getStringFromWasm0(arg0, arg1); + return ret; + }; + imports.wbg.__wbindgen_throw = function(arg0, arg1) { + throw new Error(getStringFromWasm0(arg0, arg1)); + }; + + return imports; +} + +function __wbg_init_memory(imports, memory) { + +} + +function __wbg_finalize_init(instance, module) { + wasm = instance.exports; + __wbg_init.__wbindgen_wasm_module = module; + cachedDataViewMemory0 = null; + cachedUint8ArrayMemory0 = null; + + + wasm.__wbindgen_start(); + return wasm; +} + +function initSync(module) { + if (wasm !== undefined) return wasm; + + + if (typeof module !== 'undefined') { + if (Object.getPrototypeOf(module) === Object.prototype) { + ({module} = module) + } else { + console.warn('using deprecated parameters for `initSync()`; pass a single object instead') + } + } + + const imports = __wbg_get_imports(); + + __wbg_init_memory(imports); + + if (!(module instanceof WebAssembly.Module)) { + module = new WebAssembly.Module(module); + } + + const instance = new WebAssembly.Instance(module, imports); + + return __wbg_finalize_init(instance, module); +} + +async function __wbg_init(module_or_path) { + if (wasm !== undefined) return wasm; + + + if (typeof module_or_path !== 'undefined') { + if (Object.getPrototypeOf(module_or_path) === Object.prototype) { + ({module_or_path} = module_or_path) + } else { + console.warn('using deprecated parameters for the initialization function; pass a single object instead') + } + } + + + const imports = __wbg_get_imports(); + + if (typeof module_or_path === 'string' || (typeof Request === 'function' && module_or_path instanceof Request) || (typeof URL === 'function' && module_or_path instanceof URL)) { + module_or_path = fetch(module_or_path); + } + + __wbg_init_memory(imports); + + const { instance, module } = await __wbg_load(await module_or_path, imports); + + return __wbg_finalize_init(instance, module); +} + +export { initSync }; +export default __wbg_init; diff --git a/src/matrix-rtc-sdk/generated/wasm-bindgen/index_bg.wasm b/src/matrix-rtc-sdk/generated/wasm-bindgen/index_bg.wasm new file mode 100644 index 0000000000000000000000000000000000000000..26f57cbad674a856f1439b2882b63625eba4bc7e GIT binary patch literal 1553078 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Ʊ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%0Do{FDjJkH!<=|g8pvJrB^WuLB}Ez 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

C-5JO3v*4R_W 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

2`Bv)q6CAHg)oMy{SzIwSeO3(3moT^0&D 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

RSeyL?K>N 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%0Do;oznOTb6Cxa9^- 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 a0fW?lcSJ^~R!)-o% { + beforeAll(async () => { + await initMatrixRtcSdkForTests(); + }); + + it("computes a session from raw events without a manager", () => { + const join = JSON.stringify({ + type: "m.rtc.member", + sender: "@alice:example.org", + event_id: "$1", + room_id: ROOM_ID, + origin_server_ts: Date.now(), + msc4354_sticky: { duration_ms: 240_000 }, + content: { + slot_id: "m.call#ROOM", + msc4354_sticky_key: "m-1", + member: { id: "m-1", membership: "join" }, + application: { type: "m.call" }, + transports: { + published: [ + { type: "livekit", livekit_service_url: "https://lk.example.org" }, + ], + can_subscribe: ["livekit"], + }, + }, + }); + const [session] = computeSessionsFromEvents( + [join], + FfiElementCallCompat.StickyEvents, + ); + expect(session.memberCount).toBe(1); + expect(session.members[0].eventId).toBe("$1"); + expect(session.isActive).toBe(true); + }); + + it("constructs a manager over a TypeScript driver and starts disconnected", () => { + const driver = new FfiMatrixDriver(new InertDriver()); + const manager = new FfiParticipationManager( + ROOM_ID, + "m.call#ROOM", + "@me:example.org", + "MYDEV", + driver, + { + compat: FfiElementCallCompat.StickyEvents, + manageMediaKeys: false, + requireCrossSignedSender: false, + useKeyDelayMs: 1000n, + }, + ); + expect(FfiStatus.Disconnected.instanceOf(manager.status())).toBe(true); + expect(manager.memberships()).toEqual([]); + expect(manager.ownTransportIdentity()).toBeUndefined(); + manager.uniffiDestroy(); + }); +}); + +/** A driver that answers every read with nothing and never sends. */ +class InertDriver implements MatrixDriverCallback { + public async sendStickyEvent(): Promise { + return Promise.resolve({ eventId: "$sticky", delayId: undefined }); + } + public async sendStateEvent(): Promise { + return Promise.resolve({ eventId: "$state", delayId: undefined }); + } + public async sendDelayedEvent(): Promise { + return Promise.resolve("delay"); + } + public async sendDelayedStateEvent(): Promise { + return Promise.resolve("delay"); + } + public async restartDelayedEvent(): Promise { + return Promise.resolve(); + } + public async cancelDelayedEvent(): Promise { + return Promise.resolve(); + } + public async delegateLivekitDelayedLeave(): Promise { + return Promise.resolve(); + } + public async sendToDevice( + recipients: FfiToDeviceRecipient[], + ): Promise { + return Promise.resolve( + recipients.map((recipient) => ({ recipient, error: undefined })), + ); + } + public async getRtcTransports(): Promise { + return Promise.resolve([]); + } + public async getLivekitToken( + request: FfiLivekitTokenRequest, + ): Promise { + return Promise.resolve({ jwt: "jwt", url: request.url }); + } + public async readEvents(): Promise { + return Promise.resolve([]); + } + public async readState(): Promise { + return Promise.resolve([]); + } + public subscribeRoomEvents(): void {} + public subscribeToDeviceEvents(): void {} + public subscribeStateUpdates(): void {} + public subscribeConnectivity(): void {} + public isHomeserverConnected(): boolean { + return true; + } +} diff --git a/src/matrix-rtc-sdk/index.ts b/src/matrix-rtc-sdk/index.ts new file mode 100644 index 000000000..6db8b385d --- /dev/null +++ b/src/matrix-rtc-sdk/index.ts @@ -0,0 +1,90 @@ +/* +Copyright 2026 Element Creations Ltd. + +SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial +Please see LICENSE in the repository root for full details. +*/ + +/** + * The MatrixRTC SDK: the Rust `matrix-rtc` crate through its uniffi web + * bindings. Everything Element Call needs to *participate* in a MatrixRTC + * session — the session projection, our own membership with its keep-alive, + * transport tokens and the media key exchange — lives in the crate; this + * module loads it and re-exports the surface Element Call uses. + * + * The bindings under `generated/` are vendored by + * `scripts/sync-matrix-rtc-sdk.sh` and never edited by hand. + */ + +import initAsync, { type InitInput } from "./generated/wasm-bindgen/index.js"; +import bindings from "./generated/matrix_rtc"; + +export { + FfiMatrixDriver, + FfiParticipationManager, + FfiElementCallCompat, + FfiEventOrigin, + FfiStatus, + FfiDisconnectCause, + FfiJoinError, + FfiKeepAlive, + FfiMembershipState, + FfiTransportIntent, + RtcError, + computeSessionsFromEvents, +} from "./generated/matrix_rtc"; +export type { + FfiConnectionData, + FfiConnectionWithMembers, + FfiJoinParams, + FfiLivekitToken, + FfiLivekitTokenRequest, + FfiMediaKey, + FfiMember, + FfiMembership, + FfiParticipationConfig, + FfiRtcTransport, + FfiSendEventResponse, + FfiSessionSnapshot, + FfiToDeviceDelivery, + FfiToDeviceRecipient, + ConnectivitySinkLike, + MatrixDriverCallback, + RoomEventSinkLike, + StateUpdateSinkLike, + ToDeviceSinkLike, +} from "./generated/matrix_rtc"; + +/** + * Where to load the wasm from. A URL (or anything `fetch` accepts) in a + * browser; bytes or a compiled module where there is nothing to fetch from, + * such as tests. + */ +export type MatrixRtcWasmSource = InitInput; + +let loading: Promise | null = null; + +/** + * Loads and initialises the SDK. Idempotent: the first call decides the + * source, later calls await the same load. + * + * Without a `source`, the wasm is the one bundled next to this module (an + * asset URL in the app builds). A host that serves the file from somewhere + * else, or a test runner with no server, passes its own. + */ +export async function initMatrixRtcSdk( + source?: MatrixRtcWasmSource, +): Promise { + loading ??= (async (): Promise => { + await initAsync({ module_or_path: source ?? (await bundledWasm()) }); + bindings.initialize(); + })(); + await loading; +} + +/** The wasm as the bundler placed it, resolved lazily so nothing is fetched until needed. */ +async function bundledWasm(): Promise { + const { default: url } = + await import("./generated/wasm-bindgen/index_bg.wasm?url"); + return url; +} diff --git a/src/state/rtc/CallParticipation.test.ts b/src/state/rtc/CallParticipation.test.ts new file mode 100644 index 000000000..e768f39f0 --- /dev/null +++ b/src/state/rtc/CallParticipation.test.ts @@ -0,0 +1,393 @@ +/* +Copyright 2026 Element Creations Ltd. + +SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial +Please see LICENSE in the repository root for full details. +*/ + +import { beforeAll, describe, expect, it } from "vitest"; + +import { MatrixRTCMode } from "../../config/ConfigOptions"; +import { + MOCK_LK_SERVICE_URL, + MockRtcMatrixDriver, + roomEncryptionEvent, + slotEvent, + waitFor, +} from "../../driver/MockRtcMatrixDriver"; +import { + FfiDisconnectCause, + FfiElementCallCompat, + FfiStatus, + type FfiMediaKey, +} from "../../matrix-rtc-sdk"; +import { initMatrixRtcSdkForTests } from "../../utils/test-matrix-rtc"; +import { testScope } from "../../utils/test"; +import { ObservableScope } from "../ObservableScope"; +import { CallParticipation } from "./CallParticipation"; +import { errorForStatus } from "./errors"; +import { + compatForMode, + joinParamsFromConfig, + participationConfig, +} from "./joinParams"; +import { publishOnLivekit, receiveOnly } from "./transportIntent"; +import { + MatrixRTCTransportMissingError, + NoOpenSlotError, + StickyEventsRequiredError, +} from "../../utils/errors"; + +const session = { + delayed_leave: { delay_ms: 15_000 }, + delegated_delayed_leave: { delay_ms: 3_600_000 }, + network_error_retry_ms: 1000, + wait_for_key_rotation_ms: 50, +}; + +const joinParams = joinParamsFromConfig({ + session, + delegateDelayedLeave: false, +}); + +function create( + driver: MockRtcMatrixDriver, + overrides: { manageMediaKeys?: boolean; transportFallbackUrl?: string } = {}, + scope = testScope(), +): CallParticipation { + return new CallParticipation( + scope, + driver, + driver.roomId, + driver.userId, + driver.deviceId, + { + config: participationConfig({ + mode: MatrixRTCMode.Matrix_2_0, + manageMediaKeys: overrides.manageMediaKeys ?? true, + session, + }), + transportFallbackUrl: overrides.transportFallbackUrl, + }, + ); +} + +/** A room where nobody has started a call yet, and we may. */ +const openSlot = { encrypted: false, canOpen: true }; + +const peer = { + userId: "@peer:example.org", + deviceId: "PEERDEV", + memberId: "m-peer", +}; + +describe("CallParticipation", () => { + beforeAll(async () => { + await initMatrixRtcSdkForTests(); + }); + + it("starts disconnected and follows a remote member in and out", async () => { + // somebody already started the call: the slot is open + const driver = new MockRtcMatrixDriver({ + roomState: [slotEvent({ status: "open" })], + }); + const callParticipation = create(driver); + expect( + FfiStatus.Disconnected.instanceOf(callParticipation.status$.value), + ).toBe(true); + expect(callParticipation.memberships$.value.value).toEqual([]); + + driver.peerJoins(peer); + // getters are fresh at once; the listener fires a tick later + await waitFor( + "peer listed", + () => callParticipation.memberships$.value.value.length === 1, + ); + const [membership] = callParticipation.memberships$.value.value; + expect(membership.member.memberId).toBe(peer.memberId); + expect(membership.connections).toEqual([MOCK_LK_SERVICE_URL]); + expect(callParticipation.session$.value.memberCount).toBe(1); + + driver.peerLeaves(peer); + await waitFor( + "peer gone", + () => callParticipation.memberships$.value.value.length === 0, + ); + }); + + it("joins publishing, exposes our identity before the echo and our membership after it", async () => { + const driver = new MockRtcMatrixDriver(); + const callParticipation = create(driver); + await callParticipation.join(publishOnLivekit(), joinParams, openSlot); + + expect( + FfiStatus.Connected.instanceOf(callParticipation.status$.value), + ).toBe(true); + const ownMemberId = callParticipation.ownMemberId$.value; + expect(ownMemberId).toBeTruthy(); + expect(callParticipation.ownTransportIdentity$.value).toBeTruthy(); + // nobody had started a call: we opened the slot before joining + expect(callParticipation.session$.value.slotOpen).toBe(true); + const [slot] = driver.calls("stateEvent"); + expect(slot.eventType).toBe("org.matrix.msc4143.rtc.slot"); + expect(slot.stateKey).toBe("m.call#ROOM"); + expect(slot.content).toEqual({ + status: "open", + application: { type: "m.call" }, + }); + + await waitFor( + "own echo", + () => callParticipation.ownMembership$.value !== null, + ); + expect(callParticipation.ownMembership$.value?.member.memberId).toBe( + ownMemberId, + ); + expect(callParticipation.ownMembership$.value?.transportIdentity).toBe( + callParticipation.ownTransportIdentity$.value, + ); + expect(callParticipation.connections$.value).toHaveLength(1); + expect(callParticipation.connections$.value[0].connection.serviceUrl).toBe( + MOCK_LK_SERVICE_URL, + ); + // discovery: the bare intent asked the homeserver + expect(driver.calls("getRtcTransports")).toHaveLength(1); + expect(driver.calls("getLivekitToken")[0].slotId).toBe("m.call#ROOM"); + + await callParticipation.leave(); + const status = callParticipation.status$.value; + expect(FfiStatus.Disconnected.instanceOf(status)).toBe(true); + if (FfiStatus.Disconnected.instanceOf(status)) + expect(FfiDisconnectCause.LeftByHost.instanceOf(status.inner.cause)).toBe( + true, + ); + // ...and again: a manager can be reused, with a fresh member id + await callParticipation.join(publishOnLivekit(), joinParams, openSlot); + expect(callParticipation.ownMemberId$.value).not.toBe(ownMemberId); + await callParticipation.leave(); + }); + + it("does not open a slot that is already open, and refuses to join without the power to open one", async () => { + const open = new MockRtcMatrixDriver({ + roomState: [slotEvent({ status: "open" })], + }); + const p1 = create(open); + await p1.join(receiveOnly(), joinParams, { + encrypted: false, + canOpen: false, + }); + expect(open.calls("stateEvent")).toEqual([]); + await p1.leave(); + + const closed = new MockRtcMatrixDriver(); + const p2 = create(closed); + await expect( + p2.join(receiveOnly(), joinParams, { encrypted: false, canOpen: false }), + ).rejects.toBeInstanceOf(NoOpenSlotError); + expect(closed.calls("stateEvent")).toEqual([]); + expect(closed.calls("stickyEvent")).toEqual([]); + expect(FfiStatus.Disconnected.instanceOf(p2.status$.value)).toBe(true); + + // an encrypted room gets a slot that prescribes per-member keys + const encryptedRoom = new MockRtcMatrixDriver({ + roomState: [roomEncryptionEvent()], + }); + const p3 = create(encryptedRoom); + await p3.join(receiveOnly(), joinParams, { + encrypted: true, + canOpen: true, + }); + expect(encryptedRoom.calls("stateEvent")[0].content).toEqual({ + status: "open", + application: { type: "m.call" }, + encryption: { type: "m.per_member" }, + }); + expect(p3.session$.value.encrypted).toBe(true); + await p3.leave(); + }); + + it("falls back to the configured transport when the homeserver has none or fails", async () => { + const none = new MockRtcMatrixDriver({ transports: [] }); + const p1 = create(none, { transportFallbackUrl: "https://lk.config" }); + await p1.join(publishOnLivekit(), joinParams, openSlot); + expect(none.calls("getLivekitToken")[0].url).toBe("https://lk.config"); + await p1.leave(); + + const failing = new MockRtcMatrixDriver(); + failing.failTransportDiscovery = true; + const p2 = create(failing, { transportFallbackUrl: "https://lk.config" }); + await p2.join(publishOnLivekit(), joinParams, openSlot); + expect(failing.calls("getLivekitToken")[0].url).toBe("https://lk.config"); + await p2.leave(); + + // a custom URL in the intent skips discovery altogether + const custom = new MockRtcMatrixDriver(); + const p3 = create(custom); + await p3.join(publishOnLivekit("https://lk.custom"), joinParams, openSlot); + expect(custom.calls("getRtcTransports")).toHaveLength(0); + expect(custom.calls("getLivekitToken")[0].url).toBe("https://lk.custom"); + await p3.leave(); + }); + + it("streams key changes and filters members that left holding our key", async () => { + const driver = new MockRtcMatrixDriver({ + roomState: [ + roomEncryptionEvent(), + slotEvent({ status: "open", encrypted: true }), + ], + }); + const callParticipation = create(driver); + const changes: FfiMediaKey[] = []; + callParticipation.keyChanges$.subscribe((k) => changes.push(k)); + driver.addPeer(peer); + await callParticipation.join(receiveOnly(), joinParams, openSlot); + driver.peerJoins(peer); + await waitFor("peer key", () => + callParticipation.keyMap$.value.some((k) => k.memberId === peer.memberId), + ); + expect(changes.some((k) => k.memberId === peer.memberId)).toBe(true); + driver.peerLeaves(peer); + // the crate keeps a LeftWithKeys entry; the behavior does not + await waitFor( + "peer gone from memberships", + () => + !callParticipation.memberships$.value.value.some( + (m) => m.member.memberId === peer.memberId, + ), + ); + await callParticipation.leave(); + }); + + it("does not exchange keys when the call manages none", async () => { + const driver = new MockRtcMatrixDriver(); + const callParticipation = create(driver, { manageMediaKeys: false }); + driver.addPeer(peer); + await callParticipation.join(receiveOnly(), joinParams, openSlot); + driver.peerJoins(peer); + await new Promise((r) => setTimeout(r, 50)); + expect(driver.calls("toDevice")).toEqual([]); + await callParticipation.leave(); + }); + + it("surfaces a lost homeserver as a critical impairment in the status", async () => { + const driver = new MockRtcMatrixDriver(); + const callParticipation = create(driver); + await callParticipation.join(receiveOnly(), joinParams, openSlot); + driver.setHomeserverConnected(false); + await waitFor("impairment in status$", () => { + const status = callParticipation.status$.value; + return ( + FfiStatus.Connected.instanceOf(status) && + status.inner.impairments[0]?.tag === "HomeserverUnreachable" + ); + }); + driver.setHomeserverConnected(true); + await waitFor("impairment cleared", () => { + const status = callParticipation.status$.value; + return ( + FfiStatus.Connected.instanceOf(status) && + status.inner.impairments.length === 0 + ); + }); + await callParticipation.leave(); + }); + + it("leaves and destroys the manager when the scope ends", async () => { + const driver = new MockRtcMatrixDriver(); + const scope = new ObservableScope(); + const callParticipation = create(driver, {}, scope); + await callParticipation.join(receiveOnly(), joinParams, openSlot); + scope.end(); + await waitFor( + "leave sent", + () => + driver + .calls("stickyEvent") + .some( + (c) => + c.content.member === undefined || + c.content.msc4354_sticky_key !== undefined, + ) && driver.calls("cancelDelayed").length === 1, + ); + expect(callParticipation.debugSnapshot()).toBe("{}"); + await expect( + callParticipation.join(receiveOnly(), joinParams, openSlot), + ).rejects.toThrow("ended"); + }); + + it("turns terminal causes into Element Call errors", async () => { + const driver = new MockRtcMatrixDriver({ transports: [] }); + const callParticipation = create(driver); + await expect( + callParticipation.join(publishOnLivekit(), joinParams, openSlot), + ).rejects.toThrow(); + expect( + errorForStatus(callParticipation.status$.value, { + domain: "example.org", + stickyEventsSupported: true, + }), + ).toBeInstanceOf(MatrixRTCTransportMissingError); + + const noSticky = new MockRtcMatrixDriver(); + noSticky.refuseStickyEvents = true; + const p2 = create(noSticky); + await expect( + p2.join(receiveOnly(), joinParams, openSlot), + ).rejects.toThrow(); + expect( + errorForStatus(p2.status$.value, { + domain: "example.org", + stickyEventsSupported: false, + }), + ).toBeInstanceOf(StickyEventsRequiredError); + + const fine = create(new MockRtcMatrixDriver()); + expect( + errorForStatus(fine.status$.value, { + domain: "example.org", + stickyEventsSupported: true, + }), + ).toBeNull(); + }); + + it("derives the crate's parameters from Element Call's config", () => { + expect(compatForMode(MatrixRTCMode.Compatibility)).toBe( + FfiElementCallCompat.StateEvents, + ); + expect(compatForMode(MatrixRTCMode.Matrix_2_0)).toBe( + FfiElementCallCompat.StickyEvents, + ); + expect(joinParams).toEqual({ + applicationType: "m.call", + intent: undefined, + // js-sdk's 4 h default, capped at the sticky hour + stickyDurationMs: 3_600_000n, + keepAliveTimeoutMs: 15_000n, + degradedLifetimeMs: undefined, + delegateDelayedLeave: false, + }); + expect( + joinParamsFromConfig({ + session: { ...session, membership_event_expiry_ms: 60_000 }, + callIntent: "video", + delegateDelayedLeave: true, + }), + ).toMatchObject({ + intent: "video", + stickyDurationMs: 60_000n, + delegateDelayedLeave: true, + }); + expect( + participationConfig({ + mode: MatrixRTCMode.Compatibility, + manageMediaKeys: false, + session, + }), + ).toEqual({ + compat: FfiElementCallCompat.StateEvents, + manageMediaKeys: false, + requireCrossSignedSender: false, + useKeyDelayMs: 50n, + }); + }); +}); diff --git a/src/state/rtc/CallParticipation.ts b/src/state/rtc/CallParticipation.ts new file mode 100644 index 000000000..fd9638618 --- /dev/null +++ b/src/state/rtc/CallParticipation.ts @@ -0,0 +1,494 @@ +/* +Copyright 2026 Element Creations Ltd. + +SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial +Please see LICENSE in the repository root for full details. +*/ + +import { logger as rootLogger, type Logger } from "matrix-js-sdk/lib/logger"; +import { + BehaviorSubject, + type Observable, + Subject, + combineLatest, + map, +} from "rxjs"; + +import { type RtcMatrixDriver } from "../../driver/RtcMatrixDriver"; +import { + FfiMatrixDriver, + FfiMembershipState, + FfiParticipationManager, + FfiStatus, + type FfiConnectionWithMembers, + type FfiJoinParams, + type FfiLivekitToken, + type FfiLivekitTokenRequest, + type FfiMediaKey, + type FfiMembership, + type FfiParticipationConfig, + type FfiRtcTransport, + type FfiSendEventResponse, + type FfiSessionSnapshot, + type FfiToDeviceDelivery, + type FfiToDeviceRecipient, + type FfiTransportIntent, + type ConnectivitySinkLike, + type RoomEventSinkLike, + type StateUpdateSinkLike, + type ToDeviceSinkLike, +} from "../../matrix-rtc-sdk"; +import { type Behavior } from "../Behavior"; +import { Epoch, type ObservableScope, trackEpoch } from "../ObservableScope"; +import { NoOpenSlotError } from "../../utils/errors"; +import { ELEMENT_CALL_APPLICATION, ELEMENT_CALL_SLOT_ID } from "./slot"; +import { LIVEKIT_TRANSPORT_TYPE } from "./transportIntent"; + +/** + * What to do about the room's slot when joining. A call needs an open + * MatrixRTC slot (`m.rtc.slot` state); a room that never had a call has + * none, and the client that starts the call opens it — if its user has the + * power level to send the state event. + */ +export interface SlotPolicy { + /** Whether the slot, if we open it, prescribes per-member media encryption (an encrypted room). */ + encrypted: boolean; + /** Whether this user may send the slot state event (`RoomInfo.canOpenSlot`). */ + canOpen: boolean; +} + +/** How long to wait for the seed, and for our own slot event to echo back. */ +const SLOT_WAIT_MS = 15_000; + +export interface CallParticipationOptions { + /** One manager per `(room, slot)`; Element Call has one slot per room. */ + slotId?: string; + config: FfiParticipationConfig; + /** + * A LiveKit service URL to fall back on when the homeserver advertises no + * transport (or cannot be asked) — Element Call's `config.json` value, + * which is Element Call's business rather than the host's. + */ + transportFallbackUrl?: string; + logger?: Logger; +} + +/** + * Element Call's view of one participation in a MatrixRTC session: the + * crate's `FfiParticipationManager` as behaviors. "Participation" is the + * crate's word for the FFI side; this is the RxJS wrapper a call is built on. + * + * The crate does everything Matrix: it projects the session from the + * driver's events, publishes and keeps alive our own membership, mints + * transport tokens and exchanges media keys. This class owns the manager + * for the scope's lifetime, seeds each behavior from the manager's getter and + * keeps it current from the manager's listener, and ends the participation + * (leaving if still joined) when the scope ends. + */ +export class CallParticipation { + private readonly logger: Logger; + private readonly matrixDriver: FfiMatrixDriver; + private readonly manager: FfiParticipationManager; + private ended = false; + + private readonly membershipsSubject$: BehaviorSubject; + private readonly connectionsSubject$: BehaviorSubject< + FfiConnectionWithMembers[] + >; + private readonly keyMapSubject$: BehaviorSubject; + private readonly keyChangesSubject$ = new Subject(); + private readonly statusSubject$: BehaviorSubject; + private readonly sessionSubject$: BehaviorSubject; + private readonly ownMemberIdSubject$: BehaviorSubject; + private readonly ownTransportIdentitySubject$: BehaviorSubject; + + /** + * One entry per joined member, ourselves included once our own membership + * has echoed back from the homeserver. Members that left but may still hold + * our media key (`LeftWithKeys`) are not listed. + */ + public readonly memberships$: Behavior>; + /** The LiveKit rooms to hold, with the token for each. */ + public readonly connections$: Behavior; + /** Every media key in use, ours and theirs, one per (member, index). */ + public readonly keyMap$: Behavior; + /** The single key that changed, as it changes. */ + public readonly keyChanges$: Observable = + this.keyChangesSubject$; + public readonly status$: Behavior; + /** Slot open?, encrypted?, member count, seed honesty. */ + public readonly session$: Behavior; + /** Our member id, from the moment `join()` starts; null while not joined. */ + public readonly ownMemberId$: Behavior; + /** Our LiveKit participant identity, known as early as the member id. */ + public readonly ownTransportIdentity$: Behavior; + /** Our own entry in `memberships$`, once echoed. */ + public readonly ownMembership$: Behavior; + + public constructor( + scope: ObservableScope, + driver: RtcMatrixDriver, + roomId: string, + userId: string, + deviceId: string, + options: CallParticipationOptions, + ) { + this.logger = (options.logger ?? rootLogger).getChild( + "[CallParticipation]", + ); + const rtcDriver = + options.transportFallbackUrl === undefined + ? driver + : new TransportFallbackDriver( + driver, + options.transportFallbackUrl, + this.logger, + ); + this.matrixDriver = new FfiMatrixDriver(rtcDriver); + this.manager = new FfiParticipationManager( + roomId, + options.slotId ?? ELEMENT_CALL_SLOT_ID, + userId, + deviceId, + this.matrixDriver, + options.config, + ); + + this.membershipsSubject$ = new BehaviorSubject( + joinedOnly(this.manager.memberships()), + ); + this.connectionsSubject$ = new BehaviorSubject(this.manager.connections()); + this.keyMapSubject$ = new BehaviorSubject(this.manager.keyMap()); + this.statusSubject$ = new BehaviorSubject(this.manager.status()); + this.sessionSubject$ = new BehaviorSubject(this.manager.session()); + this.ownMemberIdSubject$ = new BehaviorSubject( + this.manager.ownMemberId() ?? null, + ); + this.ownTransportIdentitySubject$ = new BehaviorSubject( + this.manager.ownTransportIdentity() ?? null, + ); + + this.manager.setMembershipsListener({ + onMembershipsChange: (memberships) => { + if (this.ended) return; + this.membershipsSubject$.next(joinedOnly(memberships)); + this.sessionSubject$.next(this.manager.session()); + this.refreshOwnIdentity(); + }, + }); + this.manager.setConnectionsListener({ + onConnectionsChange: (connections) => { + if (!this.ended) this.connectionsSubject$.next(connections); + }, + }); + this.manager.setKeyMapListener({ + onKeyMapChange: (keyMap, change) => { + if (this.ended) return; + this.keyMapSubject$.next(keyMap); + this.keyChangesSubject$.next(change); + }, + }); + this.manager.setStatusListener({ + onStatusChange: (status) => { + if (this.ended) return; + this.statusSubject$.next(status); + this.sessionSubject$.next(this.manager.session()); + this.refreshOwnIdentity(); + }, + }); + this.manager.setKeyRejectedListener({ + onKeyRejected: (memberId, reason) => + this.logger.warn(`Discarded a media key from ${memberId}: ${reason}`), + }); + + this.memberships$ = scope.behavior( + this.membershipsSubject$.pipe(trackEpoch()), + new Epoch(this.membershipsSubject$.value), + ); + this.connections$ = scope.behavior(this.connectionsSubject$); + this.keyMap$ = scope.behavior(this.keyMapSubject$); + this.status$ = scope.behavior(this.statusSubject$); + this.session$ = scope.behavior(this.sessionSubject$); + this.ownMemberId$ = scope.behavior(this.ownMemberIdSubject$); + this.ownTransportIdentity$ = scope.behavior( + this.ownTransportIdentitySubject$, + ); + this.ownMembership$ = scope.behavior( + combineLatest([this.memberships$, this.ownMemberId$]).pipe( + map( + ([memberships, ownMemberId]) => + memberships.value.find((m) => m.member.memberId === ownMemberId) ?? + null, + ), + ), + ); + + scope.onEnd(() => void this.end()); + } + + /** + * Join the session, opening the room's slot first when nobody has + * (`slot`). Resolves once our membership is published, or rejects: with + * {@link NoOpenSlotError} when there is no slot and we may not open one, + * otherwise with the crate's typed error. The status keeps reporting from + * there. + */ + public async join( + intent: FfiTransportIntent, + params: FfiJoinParams, + slot: SlotPolicy, + ): Promise { + if (this.ended) throw new Error("The participation has ended"); + try { + await this.ensureOpenSlot(slot); + await this.manager.join(intent, params); + } finally { + this.refreshAll(); + } + } + + private async ensureOpenSlot(slot: SlotPolicy): Promise { + // The crate's own `join` waits for the seed too, but the slot check has + // to come first: a slot read that has not finished looks like no slot. + await this.waitUntil( + () => this.manager.session().seeded, + "the session seed", + ); + if (this.manager.session().slotOpen === true) return; + if (!slot.canOpen) throw new NoOpenSlotError(); + this.logger.info( + `No open slot in the room; opening ${ELEMENT_CALL_SLOT_ID} (encrypted: ${slot.encrypted})`, + ); + await this.manager.openSlot(ELEMENT_CALL_APPLICATION, slot.encrypted); + // Open only once the homeserver has echoed the state back. + await this.waitUntil( + () => this.manager.session().slotOpen === true, + "our slot event to echo back", + ); + } + + private async waitUntil( + condition: () => boolean, + what: string, + ): Promise { + const deadline = Date.now() + SLOT_WAIT_MS; + while (!condition()) { + if (this.ended) throw new Error("The participation has ended"); + if (Date.now() > deadline) + throw new Error(`Timed out waiting for ${what}`); + await new Promise((resolve) => setTimeout(resolve, 20)); + } + } + + /** Leave the session. A no-op when not joined. */ + public async leave(code?: string, reason?: string): Promise { + if (this.ended) return; + if (FfiStatus.Disconnected.instanceOf(this.manager.status())) return; + try { + await this.manager.leave(code, reason); + } finally { + this.refreshAll(); + } + } + + /** The crate's diagnostics dump, for rageshakes. Not a UI contract. */ + public debugSnapshot(): string { + return this.ended ? "{}" : this.manager.debugSnapshot(); + } + + private refreshOwnIdentity(): void { + this.ownMemberIdSubject$.next(this.manager.ownMemberId() ?? null); + this.ownTransportIdentitySubject$.next( + this.manager.ownTransportIdentity() ?? null, + ); + } + + /** After a join or leave the getters are fresh before any listener fires. */ + private refreshAll(): void { + if (this.ended) return; + this.statusSubject$.next(this.manager.status()); + this.membershipsSubject$.next(joinedOnly(this.manager.memberships())); + this.connectionsSubject$.next(this.manager.connections()); + this.sessionSubject$.next(this.manager.session()); + this.refreshOwnIdentity(); + } + + private async end(): Promise { + if (this.ended) return; + this.ended = true; + if (!FfiStatus.Disconnected.instanceOf(this.manager.status())) { + try { + await this.manager.leave(undefined, undefined); + } catch (e) { + this.logger.warn("Could not leave the session cleanly", e); + } + } + this.keyChangesSubject$.complete(); + this.manager.uniffiDestroy(); + this.matrixDriver.uniffiDestroy(); + } +} + +function joinedOnly(memberships: FfiMembership[]): FfiMembership[] { + return memberships.filter((m) => m.state === FfiMembershipState.Joined); +} + +/** + * Answers transport discovery with a configured LiveKit service URL when the + * host's homeserver advertises none or cannot be asked — the precedence + * Element Call has always had (homeserver first, `config.json` second) — + * and delegates everything else to the host's driver untouched. + */ +class TransportFallbackDriver implements RtcMatrixDriver { + public constructor( + private readonly inner: RtcMatrixDriver, + private readonly fallbackUrl: string, + private readonly logger: Logger, + ) {} + + public async getRtcTransports(): Promise { + let transports: FfiRtcTransport[] = []; + try { + transports = await this.inner.getRtcTransports(); + } catch (e) { + this.logger.info( + "Transport discovery failed; falling back to the configured LiveKit service", + e, + ); + } + if (transports.some((t) => t.transportType === LIVEKIT_TRANSPORT_TYPE)) + return transports; + this.logger.info( + "The homeserver advertises no LiveKit transport; using the configured one", + ); + return [ + { + transportType: LIVEKIT_TRANSPORT_TYPE, + propertiesJson: JSON.stringify({ + livekit_service_url: this.fallbackUrl, + }), + }, + ]; + } + + public async sendStickyEvent( + roomId: string, + eventType: string, + contentJson: string, + durationMs: bigint, + ): Promise { + return this.inner.sendStickyEvent( + roomId, + eventType, + contentJson, + durationMs, + ); + } + public async sendStateEvent( + roomId: string, + eventType: string, + stateKey: string, + contentJson: string, + ): Promise { + return this.inner.sendStateEvent(roomId, eventType, stateKey, contentJson); + } + public async sendDelayedEvent( + roomId: string, + eventType: string, + contentJson: string, + delayMs: bigint, + stickyDurationMs: bigint | undefined, + ): Promise { + return this.inner.sendDelayedEvent( + roomId, + eventType, + contentJson, + delayMs, + stickyDurationMs, + ); + } + public async sendDelayedStateEvent( + roomId: string, + eventType: string, + stateKey: string, + contentJson: string, + delayMs: bigint, + ): Promise { + return this.inner.sendDelayedStateEvent( + roomId, + eventType, + stateKey, + contentJson, + delayMs, + ); + } + public async restartDelayedEvent( + roomId: string, + delayId: string, + ): Promise { + return this.inner.restartDelayedEvent(roomId, delayId); + } + public async cancelDelayedEvent( + roomId: string, + delayId: string, + ): Promise { + return this.inner.cancelDelayedEvent(roomId, delayId); + } + public async delegateLivekitDelayedLeave( + roomId: string, + slotId: string, + memberJson: string, + delayId: string, + livekitServiceUrl: string | undefined, + delayMs: bigint, + ): Promise { + return this.inner.delegateLivekitDelayedLeave( + roomId, + slotId, + memberJson, + delayId, + livekitServiceUrl, + delayMs, + ); + } + public async sendToDevice( + recipients: FfiToDeviceRecipient[], + eventType: string, + contentJson: string, + ): Promise { + return this.inner.sendToDevice(recipients, eventType, contentJson); + } + public async getLivekitToken( + request: FfiLivekitTokenRequest, + ): Promise { + return this.inner.getLivekitToken(request); + } + public async readEvents( + eventType: string, + stateKey: string | undefined, + limit: number, + ): Promise { + return this.inner.readEvents(eventType, stateKey, limit); + } + public async readState( + eventType: string, + stateKey: string | undefined, + ): Promise { + return this.inner.readState(eventType, stateKey); + } + public subscribeRoomEvents(sink: RoomEventSinkLike): void { + this.inner.subscribeRoomEvents(sink); + } + public subscribeToDeviceEvents(sink: ToDeviceSinkLike): void { + this.inner.subscribeToDeviceEvents(sink); + } + public subscribeStateUpdates(sink: StateUpdateSinkLike): void { + this.inner.subscribeStateUpdates(sink); + } + public subscribeConnectivity(sink: ConnectivitySinkLike): void { + this.inner.subscribeConnectivity(sink); + } + public isHomeserverConnected(): boolean { + return this.inner.isHomeserverConnected(); + } +} diff --git a/src/state/rtc/errors.ts b/src/state/rtc/errors.ts new file mode 100644 index 000000000..e28dd3320 --- /dev/null +++ b/src/state/rtc/errors.ts @@ -0,0 +1,67 @@ +/* +Copyright 2026 Element Creations Ltd. + +SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial +Please see LICENSE in the repository root for full details. +*/ + +import { + FfiDisconnectCause, + FfiJoinError, + FfiStatus, +} from "../../matrix-rtc-sdk"; +import { + ConnectionLostError, + type ElementCallError, + MatrixRTCTransportMissingError, + MembershipManagerError, + StickyEventsRequiredError, +} from "../../utils/errors"; + +export interface DisconnectContext { + /** The homeserver's domain, for the "no transport" message. */ + domain: string; + /** Whether the homeserver was found to accept sticky events. */ + stickyEventsSupported: boolean; +} + +/** + * The error a participation ended with, or null when it ended on purpose + * (never joined, or the host left). + * + * The crate splits failures into recoverable state (`impairments`, which the + * call UI shows as interruptions) and terminal causes; only the latter are + * errors here. + */ +export function errorForStatus( + status: FfiStatus, + context: DisconnectContext, +): ElementCallError | null { + if (!FfiStatus.Disconnected.instanceOf(status)) return null; + const cause = status.inner.cause; + if ( + FfiDisconnectCause.NeverJoined.instanceOf(cause) || + FfiDisconnectCause.LeftByHost.instanceOf(cause) + ) + return null; + if (FfiDisconnectCause.JoinFailed.instanceOf(cause)) { + const error = cause.inner.error; + if (FfiJoinError.NoTransport.instanceOf(error)) + return new MatrixRTCTransportMissingError(context.domain); + // A homeserver that refuses sticky events fails the very first send. + if (FfiJoinError.Driver.instanceOf(error) && !context.stickyEventsSupported) + return new StickyEventsRequiredError(); + return new MembershipManagerError(new Error(describeJoinError(error))); + } + // SlotClosed, ManagerStopped: we are out and nothing will bring us back. + return new ConnectionLostError(); +} + +function describeJoinError(error: FfiJoinError): string { + const inner: unknown = "inner" in error ? error.inner : undefined; + const message = + typeof inner === "object" && inner !== null && "message" in inner + ? inner.message + : undefined; + return typeof message === "string" ? `${error.tag}: ${message}` : error.tag; +} diff --git a/src/state/rtc/joinParams.ts b/src/state/rtc/joinParams.ts new file mode 100644 index 000000000..0ea3271bc --- /dev/null +++ b/src/state/rtc/joinParams.ts @@ -0,0 +1,104 @@ +/* +Copyright 2026 Element Creations Ltd. + +SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial +Please see LICENSE in the repository root for full details. +*/ + +import { + type ResolvedConfigOptions, + MatrixRTCMode, +} from "../../config/ConfigOptions"; +import { + FfiElementCallCompat, + type FfiJoinParams, + type FfiParticipationConfig, +} from "../../matrix-rtc-sdk"; +import { ELEMENT_CALL_APPLICATION } from "./slot"; + +/** matrix-js-sdk caps a sticky membership at an hour; so does the crate. */ +const MAX_STICKY_DURATION_MS = 60 * 60 * 1000; +/** matrix-js-sdk's default membership expiry when the config names none. */ +const DEFAULT_MEMBERSHIP_EXPIRY_MS = 4 * 60 * 60 * 1000; + +/** + * Which pre-2026 Element Call dialect the crate speaks for a given mode. + * `compatibility` is MSC3401 state events; `matrix_2_0` is the sticky + * dialect deployed Element Call clients read today. Spec MSC4143 (`Off`) + * waits until Element Call opens slots. + */ +export function compatForMode(mode: MatrixRTCMode): FfiElementCallCompat { + switch (mode) { + case MatrixRTCMode.Compatibility: + return FfiElementCallCompat.StateEvents; + case MatrixRTCMode.Matrix_2_0: + return FfiElementCallCompat.StickyEvents; + } +} + +export interface ParticipationConfigInputs { + mode: MatrixRTCMode; + /** Whether this call encrypts media with per-participant keys. */ + manageMediaKeys: boolean; + /** + * Whether to discard media keys from senders not reported as cross-signed + * (MSC4153). Off for parity with matrix-js-sdk, which never checked, and + * because a passwordless guest cannot be cross-signed. + * + * TODO: we want this on. Turning it on needs (1) the SPA's passwordless + * users to be cross-signed or given another way in, and (2) the crate to + * report the sender's verdict on the tile while the check is off + * (`FfiMediaKeyState.senderCrossSigned`, plan item C10), so the UI can + * show an unverified sender before the switch flips. + */ + requireCrossSignedSender?: boolean; + session: ResolvedConfigOptions["matrix_rtc_session"]; +} + +export function participationConfig({ + mode, + manageMediaKeys, + requireCrossSignedSender = false, + session, +}: ParticipationConfigInputs): FfiParticipationConfig { + return { + compat: compatForMode(mode), + manageMediaKeys, + requireCrossSignedSender, + useKeyDelayMs: BigInt(session.wait_for_key_rotation_ms ?? 1000), + }; +} + +export interface JoinParamsInputs { + session: ResolvedConfigOptions["matrix_rtc_session"]; + /** `m.call.intent`: what kind of call the user is starting. */ + callIntent?: string; + /** Hand the delayed leave to the SFU (MSC4195) — only where the probe said it can. */ + delegateDelayedLeave: boolean; +} + +/** + * The crate's join parameters from Element Call's `matrix_rtc_session` + * config. Keys the crate has no knob for (`restart_ms`, `restart_timeout_ms`, + * `network_error_retry_ms`, `key_rotation_participant_limit`, + * `delegated_delayed_leave.*`) have no effect any more. + */ +export function joinParamsFromConfig({ + session, + callIntent, + delegateDelayedLeave, +}: JoinParamsInputs): FfiJoinParams { + return { + applicationType: ELEMENT_CALL_APPLICATION, + intent: callIntent, + stickyDurationMs: BigInt( + Math.min( + session.membership_event_expiry_ms ?? DEFAULT_MEMBERSHIP_EXPIRY_MS, + MAX_STICKY_DURATION_MS, + ), + ), + keepAliveTimeoutMs: BigInt(session.delayed_leave.delay_ms), + degradedLifetimeMs: undefined, + delegateDelayedLeave, + }; +} diff --git a/src/state/rtc/slot.ts b/src/state/rtc/slot.ts new file mode 100644 index 000000000..137737c1a --- /dev/null +++ b/src/state/rtc/slot.ts @@ -0,0 +1,19 @@ +/* +Copyright 2026 Element Creations Ltd. + +SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial +Please see LICENSE in the repository root for full details. +*/ + +/** + * The MatrixRTC slot Element Call lives in, `{application}#{id}` per + * MSC4143. One per room: the application is a call and the id is the room's. + */ +export const ELEMENT_CALL_SLOT_ID = "m.call#ROOM"; +export const ELEMENT_CALL_APPLICATION = "m.call"; +/** + * The state event type the crate opens a slot with (the unstable spelling + * deployed homeservers know). Opening a slot needs the power level to send + * it, which is what `RoomInfo.canOpenSlot` answers. + */ +export const ELEMENT_CALL_SLOT_EVENT_TYPE = "org.matrix.msc4143.rtc.slot"; diff --git a/src/state/rtc/transportIntent.ts b/src/state/rtc/transportIntent.ts new file mode 100644 index 000000000..dac9a75c7 --- /dev/null +++ b/src/state/rtc/transportIntent.ts @@ -0,0 +1,34 @@ +/* +Copyright 2026 Element Creations Ltd. + +SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial +Please see LICENSE in the repository root for full details. +*/ + +import { FfiTransportIntent } from "../../matrix-rtc-sdk"; + +export const LIVEKIT_TRANSPORT_TYPE = "livekit"; + +/** + * Publish on LiveKit. With a `serviceUrl` (a developer's custom URL) that + * transport is used as given; without one the crate discovers it through the + * driver's `getRtcTransports`, which is where the homeserver's answer and + * Element Call's config fallback come in. + */ +export function publishOnLivekit(serviceUrl?: string): FfiTransportIntent { + return new FfiTransportIntent.Publish({ + transport: { + transportType: LIVEKIT_TRANSPORT_TYPE, + propertiesJson: JSON.stringify( + serviceUrl === undefined ? {} : { livekit_service_url: serviceUrl }, + ), + }, + }); +} + +/** Take part without publishing media: recorders, observers, tests. */ +export function receiveOnly(): FfiTransportIntent { + return new FfiTransportIntent.ReceiveOnly({ + canSubscribe: [LIVEKIT_TRANSPORT_TYPE], + }); +} diff --git a/src/utils/errors.ts b/src/utils/errors.ts index 73b904c95..40a69a633 100644 --- a/src/utils/errors.ts +++ b/src/utils/errors.ts @@ -21,6 +21,8 @@ export enum ErrorCode { INSUFFICIENT_CAPACITY_ERROR = "INSUFFICIENT_CAPACITY_ERROR", E2EE_NOT_SUPPORTED = "E2EE_NOT_SUPPORTED", STICKY_EVENTS_NOT_SUPPORTED = "STICKY_EVENTS_NOT_SUPPORTED", + /** The room has no open MatrixRTC slot and the user may not open one. */ + NO_OPEN_SLOT = "NO_OPEN_SLOT", OPEN_ID_ERROR = "OPEN_ID_ERROR", NO_MATRIX_2_AUTHORIZATION_SERVICE = "NO_MATRIX_2_0_AUTHORIZATION_SERVICE", SFU_ERROR = "SFU_ERROR", @@ -140,6 +142,20 @@ export class StickyEventsRequiredError extends ElementCallError { ); } } +/** + * A call needs an open MatrixRTC slot in the room. Nobody has opened one, and + * this user lacks the power level to send the slot state event. + */ +export class NoOpenSlotError extends ElementCallError { + public constructor() { + super( + i18n.t("error.no_open_slot"), + ErrorCode.NO_OPEN_SLOT, + ErrorCategory.CONFIGURATION_ISSUE, + i18n.t("error.no_open_slot_description"), + ); + } +} /** * Error indicating that end-to-end encryption is not supported in the current environment. diff --git a/src/utils/test-matrix-rtc.ts b/src/utils/test-matrix-rtc.ts new file mode 100644 index 000000000..09e2ed4bd --- /dev/null +++ b/src/utils/test-matrix-rtc.ts @@ -0,0 +1,31 @@ +/* +Copyright 2026 Element Creations Ltd. + +SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial +Please see LICENSE in the repository root for full details. +*/ + +import { readFileSync } from "node:fs"; +import { resolve } from "node:path"; + +import { initMatrixRtcSdk } from "../matrix-rtc-sdk"; + +/** + * Loads the MatrixRTC SDK for a unit test. The browser builds fetch the wasm + * by URL; under vitest there is no server, so the bytes come from disk. + * + * Only suites that construct a participation manager need this; do not put + * it in the global setup, where every test file would pay for the boot. + */ +export async function initMatrixRtcSdkForTests(): Promise { + // Relative to this file: under the jsdom environment `import.meta.url` is + // not a file URL and `process.cwd()` is not the repository, but vitest + // still provides `__dirname`. + const wasm = readFileSync( + resolve( + __dirname, + "../matrix-rtc-sdk/generated/wasm-bindgen/index_bg.wasm", + ), + ); + await initMatrixRtcSdk(wasm); +} diff --git a/vitest.config.ts b/vitest.config.ts index 81519325a..905ebd81d 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -57,6 +57,8 @@ export default defineConfig((configEnv) => "src/utils/test.ts", "src/utils/test-viewmodel.ts", "src/utils/test-fixtures.ts", + "src/utils/test-matrix-rtc.ts", + "src/matrix-rtc-sdk/generated/**", "playwright/**", ], },