From 5479ce91329243ed6747a87b4be9ab518fc323a2 Mon Sep 17 00:00:00 2001 From: github-actions Date: Tue, 17 Dec 2024 09:47:59 +0000 Subject: [PATCH] Bump SDK version to 0.2.72 (matrix-rust-sdk to 512a2d2662f9db8747526ae3a815653134a2b854) --- buildSrc/src/main/kotlin/BuildVersionsSDK.kt | 2 +- .../rustcomponents/sdk/matrix_sdk_ffi.kt | 862 ++++++++++++++++-- .../matrix_sdk_crypto/matrix_sdk_crypto.kt | 32 +- 3 files changed, 812 insertions(+), 84 deletions(-) diff --git a/buildSrc/src/main/kotlin/BuildVersionsSDK.kt b/buildSrc/src/main/kotlin/BuildVersionsSDK.kt index 3e48fbc..23c04b6 100644 --- a/buildSrc/src/main/kotlin/BuildVersionsSDK.kt +++ b/buildSrc/src/main/kotlin/BuildVersionsSDK.kt @@ -1,5 +1,5 @@ object BuildVersionsSDK { const val majorVersion = 0 const val minorVersion = 2 - const val patchVersion = 71 + const val patchVersion = 72 } diff --git a/sdk/sdk-android/src/main/kotlin/org/matrix/rustcomponents/sdk/matrix_sdk_ffi.kt b/sdk/sdk-android/src/main/kotlin/org/matrix/rustcomponents/sdk/matrix_sdk_ffi.kt index afc0c62..435382b 100644 --- a/sdk/sdk-android/src/main/kotlin/org/matrix/rustcomponents/sdk/matrix_sdk_ffi.kt +++ b/sdk/sdk-android/src/main/kotlin/org/matrix/rustcomponents/sdk/matrix_sdk_ffi.kt @@ -705,6 +705,9 @@ internal interface UniffiCallbackInterfaceIdentityStatusChangeListenerMethod0 : internal interface UniffiCallbackInterfaceIgnoredUsersListenerMethod0 : com.sun.jna.Callback { fun callback(`uniffiHandle`: Long,`ignoredUserIds`: RustBuffer.ByValue,`uniffiOutReturn`: Pointer,uniffiCallStatus: UniffiRustCallStatus,) } +internal interface UniffiCallbackInterfaceKnockRequestsListenerMethod0 : com.sun.jna.Callback { + fun callback(`uniffiHandle`: Long,`joinRequests`: RustBuffer.ByValue,`uniffiOutReturn`: Pointer,uniffiCallStatus: UniffiRustCallStatus,) +} internal interface UniffiCallbackInterfaceNotificationSettingsDelegateMethod0 : com.sun.jna.Callback { fun callback(`uniffiHandle`: Long,`uniffiOutReturn`: Pointer,uniffiCallStatus: UniffiRustCallStatus,) } @@ -897,6 +900,22 @@ internal open class UniffiVTableCallbackInterfaceIgnoredUsersListener( `uniffiFree` = other.`uniffiFree` } +} +@Structure.FieldOrder("call", "uniffiFree") +internal open class UniffiVTableCallbackInterfaceKnockRequestsListener( + @JvmField internal var `call`: UniffiCallbackInterfaceKnockRequestsListenerMethod0? = null, + @JvmField internal var `uniffiFree`: UniffiCallbackInterfaceFree? = null, +) : Structure() { + class UniffiByValue( + `call`: UniffiCallbackInterfaceKnockRequestsListenerMethod0? = null, + `uniffiFree`: UniffiCallbackInterfaceFree? = null, + ): UniffiVTableCallbackInterfaceKnockRequestsListener(`call`,`uniffiFree`,), Structure.ByValue + + internal fun uniffiSetValue(other: UniffiVTableCallbackInterfaceKnockRequestsListener) { + `call` = other.`call` + `uniffiFree` = other.`uniffiFree` + } + } @Structure.FieldOrder("settingsDidChange", "uniffiFree") internal open class UniffiVTableCallbackInterfaceNotificationSettingsDelegate( @@ -2165,6 +2184,22 @@ internal open class UniffiVTableCallbackInterfaceWidgetCapabilitiesProvider( + + + + + + + + + + + + + + + + @@ -2199,6 +2234,7 @@ internal interface UniffiLib : Library { uniffiCallbackInterfaceEnableRecoveryProgressListener.register(lib) uniffiCallbackInterfaceIdentityStatusChangeListener.register(lib) uniffiCallbackInterfaceIgnoredUsersListener.register(lib) + uniffiCallbackInterfaceKnockRequestsListener.register(lib) uniffiCallbackInterfaceNotificationSettingsDelegate.register(lib) uniffiCallbackInterfacePaginationStatusListener.register(lib) uniffiCallbackInterfaceProgressWatcher.register(lib) @@ -2503,6 +2539,18 @@ internal interface UniffiLib : Library { ): RustBuffer.ByValue fun uniffi_matrix_sdk_ffi_fn_method_inreplytodetails_event_id(`ptr`: Pointer,uniffi_out_err: UniffiRustCallStatus, ): RustBuffer.ByValue + fun uniffi_matrix_sdk_ffi_fn_clone_knockrequestactions(`ptr`: Pointer,uniffi_out_err: UniffiRustCallStatus, + ): Pointer + fun uniffi_matrix_sdk_ffi_fn_free_knockrequestactions(`ptr`: Pointer,uniffi_out_err: UniffiRustCallStatus, + ): Unit + fun uniffi_matrix_sdk_ffi_fn_method_knockrequestactions_accept(`ptr`: Pointer, + ): Long + fun uniffi_matrix_sdk_ffi_fn_method_knockrequestactions_decline(`ptr`: Pointer,`reason`: RustBuffer.ByValue, + ): Long + fun uniffi_matrix_sdk_ffi_fn_method_knockrequestactions_decline_and_ban(`ptr`: Pointer,`reason`: RustBuffer.ByValue, + ): Long + fun uniffi_matrix_sdk_ffi_fn_method_knockrequestactions_mark_as_seen(`ptr`: Pointer, + ): Long fun uniffi_matrix_sdk_ffi_fn_clone_lazytimelineitemprovider(`ptr`: Pointer,uniffi_out_err: UniffiRustCallStatus, ): Pointer fun uniffi_matrix_sdk_ffi_fn_free_lazytimelineitemprovider(`ptr`: Pointer,uniffi_out_err: UniffiRustCallStatus, @@ -2711,6 +2759,8 @@ internal interface UniffiLib : Library { ): Long fun uniffi_matrix_sdk_ffi_fn_method_room_reset_power_levels(`ptr`: Pointer, ): Long + fun uniffi_matrix_sdk_ffi_fn_method_room_room_events_debug_string(`ptr`: Pointer, + ): Long fun uniffi_matrix_sdk_ffi_fn_method_room_room_info(`ptr`: Pointer, ): Long fun uniffi_matrix_sdk_ffi_fn_method_room_save_composer_draft(`ptr`: Pointer,`draft`: RustBuffer.ByValue, @@ -2733,6 +2783,8 @@ internal interface UniffiLib : Library { ): Long fun uniffi_matrix_sdk_ffi_fn_method_room_subscribe_to_identity_status_changes(`ptr`: Pointer,`listener`: Long,uniffi_out_err: UniffiRustCallStatus, ): Pointer + fun uniffi_matrix_sdk_ffi_fn_method_room_subscribe_to_knock_requests(`ptr`: Pointer,`listener`: Long, + ): Long fun uniffi_matrix_sdk_ffi_fn_method_room_subscribe_to_room_info_updates(`ptr`: Pointer,`listener`: Long,uniffi_out_err: UniffiRustCallStatus, ): Pointer fun uniffi_matrix_sdk_ffi_fn_method_room_subscribe_to_typing_notifications(`ptr`: Pointer,`listener`: Long,uniffi_out_err: UniffiRustCallStatus, @@ -3119,6 +3171,8 @@ internal interface UniffiLib : Library { ): Unit fun uniffi_matrix_sdk_ffi_fn_init_callback_vtable_ignoreduserslistener(`vtable`: UniffiVTableCallbackInterfaceIgnoredUsersListener, ): Unit + fun uniffi_matrix_sdk_ffi_fn_init_callback_vtable_knockrequestslistener(`vtable`: UniffiVTableCallbackInterfaceKnockRequestsListener, + ): Unit fun uniffi_matrix_sdk_ffi_fn_init_callback_vtable_notificationsettingsdelegate(`vtable`: UniffiVTableCallbackInterfaceNotificationSettingsDelegate, ): Unit fun uniffi_matrix_sdk_ffi_fn_init_callback_vtable_paginationstatuslistener(`vtable`: UniffiVTableCallbackInterfacePaginationStatusListener, @@ -3607,6 +3661,14 @@ internal interface UniffiLib : Library { ): Short fun uniffi_matrix_sdk_ffi_checksum_method_inreplytodetails_event_id( ): Short + fun uniffi_matrix_sdk_ffi_checksum_method_knockrequestactions_accept( + ): Short + fun uniffi_matrix_sdk_ffi_checksum_method_knockrequestactions_decline( + ): Short + fun uniffi_matrix_sdk_ffi_checksum_method_knockrequestactions_decline_and_ban( + ): Short + fun uniffi_matrix_sdk_ffi_checksum_method_knockrequestactions_mark_as_seen( + ): Short fun uniffi_matrix_sdk_ffi_checksum_method_lazytimelineitemprovider_debug_info( ): Short fun uniffi_matrix_sdk_ffi_checksum_method_lazytimelineitemprovider_get_send_handle( @@ -3781,6 +3843,8 @@ internal interface UniffiLib : Library { ): Short fun uniffi_matrix_sdk_ffi_checksum_method_room_reset_power_levels( ): Short + fun uniffi_matrix_sdk_ffi_checksum_method_room_room_events_debug_string( + ): Short fun uniffi_matrix_sdk_ffi_checksum_method_room_room_info( ): Short fun uniffi_matrix_sdk_ffi_checksum_method_room_save_composer_draft( @@ -3803,6 +3867,8 @@ internal interface UniffiLib : Library { ): Short fun uniffi_matrix_sdk_ffi_checksum_method_room_subscribe_to_identity_status_changes( ): Short + fun uniffi_matrix_sdk_ffi_checksum_method_room_subscribe_to_knock_requests( + ): Short fun uniffi_matrix_sdk_ffi_checksum_method_room_subscribe_to_room_info_updates( ): Short fun uniffi_matrix_sdk_ffi_checksum_method_room_subscribe_to_typing_notifications( @@ -4097,6 +4163,8 @@ internal interface UniffiLib : Library { ): Short fun uniffi_matrix_sdk_ffi_checksum_method_ignoreduserslistener_call( ): Short + fun uniffi_matrix_sdk_ffi_checksum_method_knockrequestslistener_call( + ): Short fun uniffi_matrix_sdk_ffi_checksum_method_notificationsettingsdelegate_settings_did_change( ): Short fun uniffi_matrix_sdk_ffi_checksum_method_paginationstatuslistener_on_update( @@ -4602,6 +4670,18 @@ private fun uniffiCheckApiChecksums(lib: UniffiLib) { if (lib.uniffi_matrix_sdk_ffi_checksum_method_inreplytodetails_event_id() != 5876.toShort()) { throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") } + if (lib.uniffi_matrix_sdk_ffi_checksum_method_knockrequestactions_accept() != 25656.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_matrix_sdk_ffi_checksum_method_knockrequestactions_decline() != 65054.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_matrix_sdk_ffi_checksum_method_knockrequestactions_decline_and_ban() != 26242.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_matrix_sdk_ffi_checksum_method_knockrequestactions_mark_as_seen() != 36036.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } if (lib.uniffi_matrix_sdk_ffi_checksum_method_lazytimelineitemprovider_debug_info() != 55450.toShort()) { throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") } @@ -4863,6 +4943,9 @@ private fun uniffiCheckApiChecksums(lib: UniffiLib) { if (lib.uniffi_matrix_sdk_ffi_checksum_method_room_reset_power_levels() != 63622.toShort()) { throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") } + if (lib.uniffi_matrix_sdk_ffi_checksum_method_room_room_events_debug_string() != 37832.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } if (lib.uniffi_matrix_sdk_ffi_checksum_method_room_room_info() != 41146.toShort()) { throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") } @@ -4896,6 +4979,9 @@ private fun uniffiCheckApiChecksums(lib: UniffiLib) { if (lib.uniffi_matrix_sdk_ffi_checksum_method_room_subscribe_to_identity_status_changes() != 14290.toShort()) { throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") } + if (lib.uniffi_matrix_sdk_ffi_checksum_method_room_subscribe_to_knock_requests() != 30649.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } if (lib.uniffi_matrix_sdk_ffi_checksum_method_room_subscribe_to_room_info_updates() != 48209.toShort()) { throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") } @@ -5337,6 +5423,9 @@ private fun uniffiCheckApiChecksums(lib: UniffiLib) { if (lib.uniffi_matrix_sdk_ffi_checksum_method_ignoreduserslistener_call() != 47519.toShort()) { throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") } + if (lib.uniffi_matrix_sdk_ffi_checksum_method_knockrequestslistener_call() != 10077.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } if (lib.uniffi_matrix_sdk_ffi_checksum_method_notificationsettingsdelegate_settings_did_change() != 51708.toShort()) { throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") } @@ -10215,33 +10304,42 @@ public object FfiConverterTypeInReplyToDetails: FfiConverter uniffiRustCall { status -> - UniffiLib.INSTANCE.uniffi_matrix_sdk_ffi_fn_free_lazytimelineitemprovider(ptr, status) + UniffiLib.INSTANCE.uniffi_matrix_sdk_ffi_fn_free_knockrequestactions(ptr, status) } } } @@ -10318,55 +10416,114 @@ open class LazyTimelineItemProvider: Disposable, AutoCloseable, LazyTimelineItem fun uniffiClonePointer(): Pointer { return uniffiRustCall() { status -> - UniffiLib.INSTANCE.uniffi_matrix_sdk_ffi_fn_clone_lazytimelineitemprovider(pointer!!, status) + UniffiLib.INSTANCE.uniffi_matrix_sdk_ffi_fn_clone_knockrequestactions(pointer!!, status) } } /** - * Returns some debug information for this event timeline item. - */override fun `debugInfo`(): EventTimelineItemDebugInfo { - return FfiConverterTypeEventTimelineItemDebugInfo.lift( - callWithPointer { - uniffiRustCall() { _status -> - UniffiLib.INSTANCE.uniffi_matrix_sdk_ffi_fn_method_lazytimelineitemprovider_debug_info( - it, _status) -} - } + * Accepts the knock request by inviting the user to the room. + */ + @Throws(ClientException::class) + @Suppress("ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE") + override suspend fun `accept`() { + return uniffiRustCallAsync( + callWithPointer { thisPtr -> + UniffiLib.INSTANCE.uniffi_matrix_sdk_ffi_fn_method_knockrequestactions_accept( + thisPtr, + + ) + }, + { future, callback, continuation -> UniffiLib.INSTANCE.ffi_matrix_sdk_ffi_rust_future_poll_void(future, callback, continuation) }, + { future, continuation -> UniffiLib.INSTANCE.ffi_matrix_sdk_ffi_rust_future_complete_void(future, continuation) }, + { future -> UniffiLib.INSTANCE.ffi_matrix_sdk_ffi_rust_future_free_void(future) }, + // lift function + { Unit }, + + // Error FFI converter + ClientException.ErrorHandler, ) } - /** - * For local echoes, return the associated send handle; returns `None` for - * remote echoes. - */override fun `getSendHandle`(): SendHandle? { - return FfiConverterOptionalTypeSendHandle.lift( - callWithPointer { - uniffiRustCall() { _status -> - UniffiLib.INSTANCE.uniffi_matrix_sdk_ffi_fn_method_lazytimelineitemprovider_get_send_handle( - it, _status) -} - } + * Declines the knock request by kicking the user from the room with an + * optional reason. + */ + @Throws(ClientException::class) + @Suppress("ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE") + override suspend fun `decline`(`reason`: kotlin.String?) { + return uniffiRustCallAsync( + callWithPointer { thisPtr -> + UniffiLib.INSTANCE.uniffi_matrix_sdk_ffi_fn_method_knockrequestactions_decline( + thisPtr, + FfiConverterOptionalString.lower(`reason`), + ) + }, + { future, callback, continuation -> UniffiLib.INSTANCE.ffi_matrix_sdk_ffi_rust_future_poll_void(future, callback, continuation) }, + { future, continuation -> UniffiLib.INSTANCE.ffi_matrix_sdk_ffi_rust_future_complete_void(future, continuation) }, + { future -> UniffiLib.INSTANCE.ffi_matrix_sdk_ffi_rust_future_free_void(future) }, + // lift function + { Unit }, + + // Error FFI converter + ClientException.ErrorHandler, ) } - /** - * Returns the shields for this event timeline item. - */override fun `getShields`(`strict`: kotlin.Boolean): ShieldState? { - return FfiConverterOptionalTypeShieldState.lift( - callWithPointer { - uniffiRustCall() { _status -> - UniffiLib.INSTANCE.uniffi_matrix_sdk_ffi_fn_method_lazytimelineitemprovider_get_shields( - it, FfiConverterBoolean.lower(`strict`),_status) -} - } + * Declines the knock request by banning the user from the room with an + * optional reason. + */ + @Throws(ClientException::class) + @Suppress("ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE") + override suspend fun `declineAndBan`(`reason`: kotlin.String?) { + return uniffiRustCallAsync( + callWithPointer { thisPtr -> + UniffiLib.INSTANCE.uniffi_matrix_sdk_ffi_fn_method_knockrequestactions_decline_and_ban( + thisPtr, + FfiConverterOptionalString.lower(`reason`), + ) + }, + { future, callback, continuation -> UniffiLib.INSTANCE.ffi_matrix_sdk_ffi_rust_future_poll_void(future, callback, continuation) }, + { future, continuation -> UniffiLib.INSTANCE.ffi_matrix_sdk_ffi_rust_future_complete_void(future, continuation) }, + { future -> UniffiLib.INSTANCE.ffi_matrix_sdk_ffi_rust_future_free_void(future) }, + // lift function + { Unit }, + + // Error FFI converter + ClientException.ErrorHandler, ) } + + /** + * Marks the knock request as 'seen'. + * + * **IMPORTANT**: this won't update the current reference to this request, + * a new one with the updated value should be emitted instead. + */ + @Throws(ClientException::class) + @Suppress("ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE") + override suspend fun `markAsSeen`() { + return uniffiRustCallAsync( + callWithPointer { thisPtr -> + UniffiLib.INSTANCE.uniffi_matrix_sdk_ffi_fn_method_knockrequestactions_mark_as_seen( + thisPtr, + + ) + }, + { future, callback, continuation -> UniffiLib.INSTANCE.ffi_matrix_sdk_ffi_rust_future_poll_void(future, callback, continuation) }, + { future, continuation -> UniffiLib.INSTANCE.ffi_matrix_sdk_ffi_rust_future_complete_void(future, continuation) }, + { future -> UniffiLib.INSTANCE.ffi_matrix_sdk_ffi_rust_future_free_void(future) }, + // lift function + { Unit }, + + // Error FFI converter + ClientException.ErrorHandler, + ) + } @@ -10376,25 +10533,25 @@ open class LazyTimelineItemProvider: Disposable, AutoCloseable, LazyTimelineItem } -public object FfiConverterTypeLazyTimelineItemProvider: FfiConverter { +public object FfiConverterTypeKnockRequestActions: FfiConverter { - override fun lower(value: LazyTimelineItemProvider): Pointer { + override fun lower(value: KnockRequestActions): Pointer { return value.uniffiClonePointer() } - override fun lift(value: Pointer): LazyTimelineItemProvider { - return LazyTimelineItemProvider(value) + override fun lift(value: Pointer): KnockRequestActions { + return KnockRequestActions(value) } - override fun read(buf: ByteBuffer): LazyTimelineItemProvider { + override fun read(buf: ByteBuffer): KnockRequestActions { // The Rust code always writes pointers as 8 bytes, and will // fail to compile if they don't fit. return lift(Pointer(buf.getLong())) } - override fun allocationSize(value: LazyTimelineItemProvider) = 8UL + override fun allocationSize(value: KnockRequestActions) = 8UL - override fun write(value: LazyTimelineItemProvider, buf: ByteBuffer) { + override fun write(value: KnockRequestActions, buf: ByteBuffer) { // The Rust code always expects pointers written as 8 bytes, // and will fail to compile if they don't fit. buf.putLong(Pointer.nativeValue(lower(value))) @@ -10501,26 +10658,33 @@ public object FfiConverterTypeLazyTimelineItemProvider: FfiConverter uniffiRustCall { status -> - UniffiLib.INSTANCE.uniffi_matrix_sdk_ffi_fn_free_mediafilehandle(ptr, status) + UniffiLib.INSTANCE.uniffi_matrix_sdk_ffi_fn_free_lazytimelineitemprovider(ptr, status) } } } @@ -10597,19 +10761,18 @@ open class MediaFileHandle: Disposable, AutoCloseable, MediaFileHandleInterface fun uniffiClonePointer(): Pointer { return uniffiRustCall() { status -> - UniffiLib.INSTANCE.uniffi_matrix_sdk_ffi_fn_clone_mediafilehandle(pointer!!, status) + UniffiLib.INSTANCE.uniffi_matrix_sdk_ffi_fn_clone_lazytimelineitemprovider(pointer!!, status) } } /** - * Get the media file's path. - */ - @Throws(ClientException::class)override fun `path`(): kotlin.String { - return FfiConverterString.lift( + * Returns some debug information for this event timeline item. + */override fun `debugInfo`(): EventTimelineItemDebugInfo { + return FfiConverterTypeEventTimelineItemDebugInfo.lift( callWithPointer { - uniffiRustCallWithError(ClientException) { _status -> - UniffiLib.INSTANCE.uniffi_matrix_sdk_ffi_fn_method_mediafilehandle_path( + uniffiRustCall() { _status -> + UniffiLib.INSTANCE.uniffi_matrix_sdk_ffi_fn_method_lazytimelineitemprovider_debug_info( it, _status) } } @@ -10618,12 +10781,30 @@ open class MediaFileHandle: Disposable, AutoCloseable, MediaFileHandleInterface - @Throws(ClientException::class)override fun `persist`(`path`: kotlin.String): kotlin.Boolean { - return FfiConverterBoolean.lift( + /** + * For local echoes, return the associated send handle; returns `None` for + * remote echoes. + */override fun `getSendHandle`(): SendHandle? { + return FfiConverterOptionalTypeSendHandle.lift( callWithPointer { - uniffiRustCallWithError(ClientException) { _status -> - UniffiLib.INSTANCE.uniffi_matrix_sdk_ffi_fn_method_mediafilehandle_persist( - it, FfiConverterString.lower(`path`),_status) + uniffiRustCall() { _status -> + UniffiLib.INSTANCE.uniffi_matrix_sdk_ffi_fn_method_lazytimelineitemprovider_get_send_handle( + it, _status) +} + } + ) + } + + + + /** + * Returns the shields for this event timeline item. + */override fun `getShields`(`strict`: kotlin.Boolean): ShieldState? { + return FfiConverterOptionalTypeShieldState.lift( + callWithPointer { + uniffiRustCall() { _status -> + UniffiLib.INSTANCE.uniffi_matrix_sdk_ffi_fn_method_lazytimelineitemprovider_get_shields( + it, FfiConverterBoolean.lower(`strict`),_status) } } ) @@ -10638,25 +10819,287 @@ open class MediaFileHandle: Disposable, AutoCloseable, MediaFileHandleInterface } -public object FfiConverterTypeMediaFileHandle: FfiConverter { +public object FfiConverterTypeLazyTimelineItemProvider: FfiConverter { - override fun lower(value: MediaFileHandle): Pointer { + override fun lower(value: LazyTimelineItemProvider): Pointer { return value.uniffiClonePointer() } - override fun lift(value: Pointer): MediaFileHandle { - return MediaFileHandle(value) + override fun lift(value: Pointer): LazyTimelineItemProvider { + return LazyTimelineItemProvider(value) } - override fun read(buf: ByteBuffer): MediaFileHandle { + override fun read(buf: ByteBuffer): LazyTimelineItemProvider { // The Rust code always writes pointers as 8 bytes, and will // fail to compile if they don't fit. return lift(Pointer(buf.getLong())) } - override fun allocationSize(value: MediaFileHandle) = 8UL + override fun allocationSize(value: LazyTimelineItemProvider) = 8UL - override fun write(value: MediaFileHandle, buf: ByteBuffer) { + override fun write(value: LazyTimelineItemProvider, buf: ByteBuffer) { + // The Rust code always expects pointers written as 8 bytes, + // and will fail to compile if they don't fit. + buf.putLong(Pointer.nativeValue(lower(value))) + } +} + + +// This template implements a class for working with a Rust struct via a Pointer/Arc +// to the live Rust struct on the other side of the FFI. +// +// Each instance implements core operations for working with the Rust `Arc` and the +// Kotlin Pointer to work with the live Rust struct on the other side of the FFI. +// +// There's some subtlety here, because we have to be careful not to operate on a Rust +// struct after it has been dropped, and because we must expose a public API for freeing +// theq Kotlin wrapper object in lieu of reliable finalizers. The core requirements are: +// +// * Each instance holds an opaque pointer to the underlying Rust struct. +// Method calls need to read this pointer from the object's state and pass it in to +// the Rust FFI. +// +// * When an instance is no longer needed, its pointer should be passed to a +// special destructor function provided by the Rust FFI, which will drop the +// underlying Rust struct. +// +// * Given an instance, calling code is expected to call the special +// `destroy` method in order to free it after use, either by calling it explicitly +// or by using a higher-level helper like the `use` method. Failing to do so risks +// leaking the underlying Rust struct. +// +// * We can't assume that calling code will do the right thing, and must be prepared +// to handle Kotlin method calls executing concurrently with or even after a call to +// `destroy`, and to handle multiple (possibly concurrent!) calls to `destroy`. +// +// * We must never allow Rust code to operate on the underlying Rust struct after +// the destructor has been called, and must never call the destructor more than once. +// Doing so may trigger memory unsafety. +// +// * To mitigate many of the risks of leaking memory and use-after-free unsafety, a `Cleaner` +// is implemented to call the destructor when the Kotlin object becomes unreachable. +// This is done in a background thread. This is not a panacea, and client code should be aware that +// 1. the thread may starve if some there are objects that have poorly performing +// `drop` methods or do significant work in their `drop` methods. +// 2. the thread is shared across the whole library. This can be tuned by using `android_cleaner = true`, +// or `android = true` in the [`kotlin` section of the `uniffi.toml` file](https://mozilla.github.io/uniffi-rs/kotlin/configuration.html). +// +// If we try to implement this with mutual exclusion on access to the pointer, there is the +// possibility of a race between a method call and a concurrent call to `destroy`: +// +// * Thread A starts a method call, reads the value of the pointer, but is interrupted +// before it can pass the pointer over the FFI to Rust. +// * Thread B calls `destroy` and frees the underlying Rust struct. +// * Thread A resumes, passing the already-read pointer value to Rust and triggering +// a use-after-free. +// +// One possible solution would be to use a `ReadWriteLock`, with each method call taking +// a read lock (and thus allowed to run concurrently) and the special `destroy` method +// taking a write lock (and thus blocking on live method calls). However, we aim not to +// generate methods with any hidden blocking semantics, and a `destroy` method that might +// block if called incorrectly seems to meet that bar. +// +// So, we achieve our goals by giving each instance an associated `AtomicLong` counter to track +// the number of in-flight method calls, and an `AtomicBoolean` flag to indicate whether `destroy` +// has been called. These are updated according to the following rules: +// +// * The initial value of the counter is 1, indicating a live object with no in-flight calls. +// The initial value for the flag is false. +// +// * At the start of each method call, we atomically check the counter. +// If it is 0 then the underlying Rust struct has already been destroyed and the call is aborted. +// If it is nonzero them we atomically increment it by 1 and proceed with the method call. +// +// * At the end of each method call, we atomically decrement and check the counter. +// If it has reached zero then we destroy the underlying Rust struct. +// +// * When `destroy` is called, we atomically flip the flag from false to true. +// If the flag was already true we silently fail. +// Otherwise we atomically decrement and check the counter. +// If it has reached zero then we destroy the underlying Rust struct. +// +// Astute readers may observe that this all sounds very similar to the way that Rust's `Arc` works, +// and indeed it is, with the addition of a flag to guard against multiple calls to `destroy`. +// +// The overall effect is that the underlying Rust struct is destroyed only when `destroy` has been +// called *and* all in-flight method calls have completed, avoiding violating any of the expectations +// of the underlying Rust code. +// +// This makes a cleaner a better alternative to _not_ calling `destroy()` as +// and when the object is finished with, but the abstraction is not perfect: if the Rust object's `drop` +// method is slow, and/or there are many objects to cleanup, and it's on a low end Android device, then the cleaner +// thread may be starved, and the app will leak memory. +// +// In this case, `destroy`ing manually may be a better solution. +// +// The cleaner can live side by side with the manual calling of `destroy`. In the order of responsiveness, uniffi objects +// with Rust peers are reclaimed: +// +// 1. By calling the `destroy` method of the object, which calls `rustObject.free()`. If that doesn't happen: +// 2. When the object becomes unreachable, AND the Cleaner thread gets to call `rustObject.free()`. If the thread is starved then: +// 3. The memory is reclaimed when the process terminates. +// +// [1] https://stackoverflow.com/questions/24376768/can-java-finalize-an-object-when-it-is-still-in-scope/24380219 +// + + +/** + * A file handle that takes ownership of a media file on disk. When the handle + * is dropped, the file will be removed from the disk. + */ +public interface MediaFileHandleInterface { + + /** + * Get the media file's path. + */ + fun `path`(): kotlin.String + + fun `persist`(`path`: kotlin.String): kotlin.Boolean + + companion object +} + +/** + * A file handle that takes ownership of a media file on disk. When the handle + * is dropped, the file will be removed from the disk. + */ +open class MediaFileHandle: Disposable, AutoCloseable, MediaFileHandleInterface { + + constructor(pointer: Pointer) { + this.pointer = pointer + this.cleanable = UniffiLib.CLEANER.register(this, UniffiCleanAction(pointer)) + } + + /** + * This constructor can be used to instantiate a fake object. Only used for tests. Any + * attempt to actually use an object constructed this way will fail as there is no + * connected Rust object. + */ + @Suppress("UNUSED_PARAMETER") + constructor(noPointer: NoPointer) { + this.pointer = null + this.cleanable = UniffiLib.CLEANER.register(this, UniffiCleanAction(pointer)) + } + + protected val pointer: Pointer? + protected val cleanable: UniffiCleaner.Cleanable + + private val wasDestroyed = AtomicBoolean(false) + private val callCounter = AtomicLong(1) + + override fun destroy() { + // Only allow a single call to this method. + // TODO: maybe we should log a warning if called more than once? + if (this.wasDestroyed.compareAndSet(false, true)) { + // This decrement always matches the initial count of 1 given at creation time. + if (this.callCounter.decrementAndGet() == 0L) { + cleanable.clean() + } + } + } + + @Synchronized + override fun close() { + this.destroy() + } + + internal inline fun callWithPointer(block: (ptr: Pointer) -> R): R { + // Check and increment the call counter, to keep the object alive. + // This needs a compare-and-set retry loop in case of concurrent updates. + do { + val c = this.callCounter.get() + if (c == 0L) { + throw IllegalStateException("${this.javaClass.simpleName} object has already been destroyed") + } + if (c == Long.MAX_VALUE) { + throw IllegalStateException("${this.javaClass.simpleName} call counter would overflow") + } + } while (! this.callCounter.compareAndSet(c, c + 1L)) + // Now we can safely do the method call without the pointer being freed concurrently. + try { + return block(this.uniffiClonePointer()) + } finally { + // This decrement always matches the increment we performed above. + if (this.callCounter.decrementAndGet() == 0L) { + cleanable.clean() + } + } + } + + // Use a static inner class instead of a closure so as not to accidentally + // capture `this` as part of the cleanable's action. + private class UniffiCleanAction(private val pointer: Pointer?) : Runnable { + override fun run() { + pointer?.let { ptr -> + uniffiRustCall { status -> + UniffiLib.INSTANCE.uniffi_matrix_sdk_ffi_fn_free_mediafilehandle(ptr, status) + } + } + } + } + + fun uniffiClonePointer(): Pointer { + return uniffiRustCall() { status -> + UniffiLib.INSTANCE.uniffi_matrix_sdk_ffi_fn_clone_mediafilehandle(pointer!!, status) + } + } + + + /** + * Get the media file's path. + */ + @Throws(ClientException::class)override fun `path`(): kotlin.String { + return FfiConverterString.lift( + callWithPointer { + uniffiRustCallWithError(ClientException) { _status -> + UniffiLib.INSTANCE.uniffi_matrix_sdk_ffi_fn_method_mediafilehandle_path( + it, _status) +} + } + ) + } + + + + @Throws(ClientException::class)override fun `persist`(`path`: kotlin.String): kotlin.Boolean { + return FfiConverterBoolean.lift( + callWithPointer { + uniffiRustCallWithError(ClientException) { _status -> + UniffiLib.INSTANCE.uniffi_matrix_sdk_ffi_fn_method_mediafilehandle_persist( + it, FfiConverterString.lower(`path`),_status) +} + } + ) + } + + + + + + + companion object + +} + +public object FfiConverterTypeMediaFileHandle: FfiConverter { + + override fun lower(value: MediaFileHandle): Pointer { + return value.uniffiClonePointer() + } + + override fun lift(value: Pointer): MediaFileHandle { + return MediaFileHandle(value) + } + + override fun read(buf: ByteBuffer): MediaFileHandle { + // The Rust code always writes pointers as 8 bytes, and will + // fail to compile if they don't fit. + return lift(Pointer(buf.getLong())) + } + + override fun allocationSize(value: MediaFileHandle) = 8UL + + override fun write(value: MediaFileHandle, buf: ByteBuffer) { // The Rust code always expects pointers written as 8 bytes, // and will fail to compile if they don't fit. buf.putLong(Pointer.nativeValue(lower(value))) @@ -12639,6 +13082,12 @@ public interface RoomInterface { suspend fun `resetPowerLevels`(): RoomPowerLevels + /** + * Return a debug representation for the internal room events data + * structure, one line per entry in the resulting vector. + */ + suspend fun `roomEventsDebugString`(): List + suspend fun `roomInfo`(): RoomInfo /** @@ -12708,6 +13157,16 @@ public interface RoomInterface { fun `subscribeToIdentityStatusChanges`(`listener`: IdentityStatusChangeListener): TaskHandle + /** + * Subscribes to requests to join this room (knock member events), using a + * `listener` to be notified of the changes. + * + * The current requests to join the room will be emitted immediately + * when subscribing, along with a [`TaskHandle`] to cancel the + * subscription. + */ + suspend fun `subscribeToKnockRequests`(`listener`: KnockRequestsListener): TaskHandle + fun `subscribeToRoomInfoUpdates`(`listener`: RoomInfoListener): TaskHandle fun `subscribeToTypingNotifications`(`listener`: TypingNotificationsListener): TaskHandle @@ -14052,6 +14511,31 @@ open class Room: Disposable, AutoCloseable, RoomInterface { } + /** + * Return a debug representation for the internal room events data + * structure, one line per entry in the resulting vector. + */ + @Throws(ClientException::class) + @Suppress("ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE") + override suspend fun `roomEventsDebugString`() : List { + return uniffiRustCallAsync( + callWithPointer { thisPtr -> + UniffiLib.INSTANCE.uniffi_matrix_sdk_ffi_fn_method_room_room_events_debug_string( + thisPtr, + + ) + }, + { future, callback, continuation -> UniffiLib.INSTANCE.ffi_matrix_sdk_ffi_rust_future_poll_rust_buffer(future, callback, continuation) }, + { future, continuation -> UniffiLib.INSTANCE.ffi_matrix_sdk_ffi_rust_future_complete_rust_buffer(future, continuation) }, + { future -> UniffiLib.INSTANCE.ffi_matrix_sdk_ffi_rust_future_free_rust_buffer(future) }, + // lift function + { FfiConverterSequenceString.lift(it) }, + // Error FFI converter + ClientException.ErrorHandler, + ) + } + + @Throws(ClientException::class) @Suppress("ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE") override suspend fun `roomInfo`() : RoomInfo { @@ -14329,6 +14813,35 @@ open class Room: Disposable, AutoCloseable, RoomInterface { } + + /** + * Subscribes to requests to join this room (knock member events), using a + * `listener` to be notified of the changes. + * + * The current requests to join the room will be emitted immediately + * when subscribing, along with a [`TaskHandle`] to cancel the + * subscription. + */ + @Throws(ClientException::class) + @Suppress("ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE") + override suspend fun `subscribeToKnockRequests`(`listener`: KnockRequestsListener) : TaskHandle { + return uniffiRustCallAsync( + callWithPointer { thisPtr -> + UniffiLib.INSTANCE.uniffi_matrix_sdk_ffi_fn_method_room_subscribe_to_knock_requests( + thisPtr, + FfiConverterTypeKnockRequestsListener.lower(`listener`), + ) + }, + { future, callback, continuation -> UniffiLib.INSTANCE.ffi_matrix_sdk_ffi_rust_future_poll_pointer(future, callback, continuation) }, + { future, continuation -> UniffiLib.INSTANCE.ffi_matrix_sdk_ffi_rust_future_complete_pointer(future, continuation) }, + { future -> UniffiLib.INSTANCE.ffi_matrix_sdk_ffi_rust_future_free_pointer(future) }, + // lift function + { FfiConverterTypeTaskHandle.lift(it) }, + // Error FFI converter + ClientException.ErrorHandler, + ) + } + override fun `subscribeToRoomInfoUpdates`(`listener`: RoomInfoListener): TaskHandle { return FfiConverterTypeTaskHandle.lift( callWithPointer { @@ -24270,6 +24783,117 @@ public object FfiConverterTypeInsertData: FfiConverterRustBuffer { +/** + * An FFI representation of a request to join a room. + */ +data class KnockRequest ( + /** + * The event id of the event that contains the `knock` membership change. + */ + var `eventId`: kotlin.String, + /** + * The user id of the user who's requesting to join the room. + */ + var `userId`: kotlin.String, + /** + * The room id of the room whose access was requested. + */ + var `roomId`: kotlin.String, + /** + * The optional display name of the user who's requesting to join the room. + */ + var `displayName`: kotlin.String?, + /** + * The optional avatar url of the user who's requesting to join the room. + */ + var `avatarUrl`: kotlin.String?, + /** + * An optional reason why the user wants join the room. + */ + var `reason`: kotlin.String?, + /** + * The timestamp when this request was created. + */ + var `timestamp`: kotlin.ULong?, + /** + * Whether the knock request has been marked as `seen` so it can be + * filtered by the client. + */ + var `isSeen`: kotlin.Boolean, + /** + * A set of actions to perform for this knock request. + */ + var `actions`: KnockRequestActions +) : Disposable { + + @Suppress("UNNECESSARY_SAFE_CALL") // codegen is much simpler if we unconditionally emit safe calls here + override fun destroy() { + + Disposable.destroy(this.`eventId`) + + Disposable.destroy(this.`userId`) + + Disposable.destroy(this.`roomId`) + + Disposable.destroy(this.`displayName`) + + Disposable.destroy(this.`avatarUrl`) + + Disposable.destroy(this.`reason`) + + Disposable.destroy(this.`timestamp`) + + Disposable.destroy(this.`isSeen`) + + Disposable.destroy(this.`actions`) + + } + + companion object +} + +public object FfiConverterTypeKnockRequest: FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): KnockRequest { + return KnockRequest( + FfiConverterString.read(buf), + FfiConverterString.read(buf), + FfiConverterString.read(buf), + FfiConverterOptionalString.read(buf), + FfiConverterOptionalString.read(buf), + FfiConverterOptionalString.read(buf), + FfiConverterOptionalULong.read(buf), + FfiConverterBoolean.read(buf), + FfiConverterTypeKnockRequestActions.read(buf), + ) + } + + override fun allocationSize(value: KnockRequest) = ( + FfiConverterString.allocationSize(value.`eventId`) + + FfiConverterString.allocationSize(value.`userId`) + + FfiConverterString.allocationSize(value.`roomId`) + + FfiConverterOptionalString.allocationSize(value.`displayName`) + + FfiConverterOptionalString.allocationSize(value.`avatarUrl`) + + FfiConverterOptionalString.allocationSize(value.`reason`) + + FfiConverterOptionalULong.allocationSize(value.`timestamp`) + + FfiConverterBoolean.allocationSize(value.`isSeen`) + + FfiConverterTypeKnockRequestActions.allocationSize(value.`actions`) + ) + + override fun write(value: KnockRequest, buf: ByteBuffer) { + FfiConverterString.write(value.`eventId`, buf) + FfiConverterString.write(value.`userId`, buf) + FfiConverterString.write(value.`roomId`, buf) + FfiConverterOptionalString.write(value.`displayName`, buf) + FfiConverterOptionalString.write(value.`avatarUrl`, buf) + FfiConverterOptionalString.write(value.`reason`, buf) + FfiConverterOptionalULong.write(value.`timestamp`, buf) + FfiConverterBoolean.write(value.`isSeen`, buf) + FfiConverterTypeKnockRequestActions.write(value.`actions`, buf) + } +} + + + data class LocationContent ( var `body`: kotlin.String, var `geoUri`: kotlin.String, @@ -28860,7 +29484,8 @@ enum class Membership { INVITED, JOINED, LEFT, - KNOCKED; + KNOCKED, + BANNED; companion object } @@ -35322,6 +35947,58 @@ public object FfiConverterTypeIgnoredUsersListener: FfiConverterCallbackInterfac +/** + * A listener for receiving new requests to a join a room. + */ +public interface KnockRequestsListener { + + fun `call`(`joinRequests`: List) + + companion object +} + + + +// Put the implementation in an object so we don't pollute the top-level namespace +internal object uniffiCallbackInterfaceKnockRequestsListener { + internal object `call`: UniffiCallbackInterfaceKnockRequestsListenerMethod0 { + override fun callback(`uniffiHandle`: Long,`joinRequests`: RustBuffer.ByValue,`uniffiOutReturn`: Pointer,uniffiCallStatus: UniffiRustCallStatus,) { + val uniffiObj = FfiConverterTypeKnockRequestsListener.handleMap.get(uniffiHandle) + val makeCall = { -> + uniffiObj.`call`( + FfiConverterSequenceTypeKnockRequest.lift(`joinRequests`), + ) + } + val writeReturn = { _: Unit -> Unit } + uniffiTraitInterfaceCall(uniffiCallStatus, makeCall, writeReturn) + } + } + + internal object uniffiFree: UniffiCallbackInterfaceFree { + override fun callback(handle: Long) { + FfiConverterTypeKnockRequestsListener.handleMap.remove(handle) + } + } + + internal var vtable = UniffiVTableCallbackInterfaceKnockRequestsListener.UniffiByValue( + `call`, + uniffiFree, + ) + + // Registers the foreign callback with the Rust side. + // This method is generated for each callback interface. + internal fun register(lib: UniffiLib) { + lib.uniffi_matrix_sdk_ffi_fn_init_callback_vtable_knockrequestslistener(vtable) + } +} + +// The ffiConverter which transforms the Callbacks in to handles to pass to Rust. +public object FfiConverterTypeKnockRequestsListener: FfiConverterCallbackInterface() + + + + + /** * Delegate to notify of changes in push rules */ @@ -38370,6 +39047,31 @@ public object FfiConverterSequenceTypeIdentityStatusChange: FfiConverterRustBuff +public object FfiConverterSequenceTypeKnockRequest: FfiConverterRustBuffer> { + override fun read(buf: ByteBuffer): List { + val len = buf.getInt() + return List(len) { + FfiConverterTypeKnockRequest.read(buf) + } + } + + override fun allocationSize(value: List): ULong { + val sizeForLength = 4UL + val sizeForItems = value.map { FfiConverterTypeKnockRequest.allocationSize(it) }.sum() + return sizeForLength + sizeForItems + } + + override fun write(value: List, buf: ByteBuffer) { + buf.putInt(value.size) + value.iterator().forEach { + FfiConverterTypeKnockRequest.write(it, buf) + } + } +} + + + + public object FfiConverterSequenceTypePollAnswer: FfiConverterRustBuffer> { override fun read(buf: ByteBuffer): List { val len = buf.getInt() diff --git a/sdk/sdk-android/src/main/kotlin/uniffi/matrix_sdk_crypto/matrix_sdk_crypto.kt b/sdk/sdk-android/src/main/kotlin/uniffi/matrix_sdk_crypto/matrix_sdk_crypto.kt index 4e21ef4..a8ce84b 100644 --- a/sdk/sdk-android/src/main/kotlin/uniffi/matrix_sdk_crypto/matrix_sdk_crypto.kt +++ b/sdk/sdk-android/src/main/kotlin/uniffi/matrix_sdk_crypto/matrix_sdk_crypto.kt @@ -1384,6 +1384,15 @@ enum class UtdCause { /** * We don't have an explanation for why this UTD happened - it is probably * a bug, or a network split between the two homeservers. + * + * For example: + * + * - the keys for this event are missing, but a key storage backup exists + * and is working, so we should be able to find the keys in the backup. + * + * - the keys for this event are missing, and a key storage backup exists + * on the server, but that backup is not working on this client even + * though this device is verified. */ UNKNOWN, /** @@ -1413,15 +1422,18 @@ enum class UtdCause { UNKNOWN_DEVICE, /** * We are missing the keys for this event, but it is a "device-historical" - * message and no backup is accessible or usable. + * message and there is no key storage backup on the server, presumably + * because the user has turned it off. * * Device-historical means that the message was sent before the current * device existed (but the current user was probably a member of the room * at the time the message was sent). Not to * be confused with pre-join or pre-invite messages (see * [`UtdCause::SentBeforeWeJoined`] for that). + * + * Expected message to user: "History is not available on this device". */ - HISTORICAL_MESSAGE, + HISTORICAL_MESSAGE_AND_BACKUP_IS_DISABLED, /** * The keys for this event are intentionally withheld. * @@ -1436,7 +1448,21 @@ enum class UtdCause { * this device by cherry-picking and blocking it, in which case, no action * can be taken on our side. */ - WITHHELD_BY_SENDER; + WITHHELD_BY_SENDER, + /** + * We are missing the keys for this event, but it is a "device-historical" + * message, and even though a key storage backup does exist, we can't use + * it because our device is unverified. + * + * Device-historical means that the message was sent before the current + * device existed (but the current user was probably a member of the room + * at the time the message was sent). Not to + * be confused with pre-join or pre-invite messages (see + * [`UtdCause::SentBeforeWeJoined`] for that). + * + * Expected message to user: "You need to verify this device". + */ + HISTORICAL_MESSAGE_AND_DEVICE_IS_UNVERIFIED; companion object }