@synonymdev/react-native-pubky 0.8.0 → 0.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/README.md +52 -9
  2. package/android/src/main/java/com/pubky/PubkyModule.kt +364 -273
  3. package/android/src/main/java/uniffi/pubkycore/pubkycore.kt +1327 -0
  4. package/android/src/main/jniLibs/arm64-v8a/libpubkycore.so +0 -0
  5. package/android/src/main/jniLibs/armeabi-v7a/libpubkycore.so +0 -0
  6. package/android/src/main/jniLibs/x86/libpubkycore.so +0 -0
  7. package/android/src/main/jniLibs/x86_64/libpubkycore.so +0 -0
  8. package/ios/Frameworks/{PubkyMobile.xcframework → PubkyCore.xcframework}/Info.plist +8 -8
  9. package/ios/Frameworks/{PubkyMobile.xcframework → PubkyCore.xcframework}/ios-arm64/Headers/module.modulemap +2 -2
  10. package/ios/Frameworks/PubkyCore.xcframework/ios-arm64/Headers/pubkycoreFFI.h +297 -0
  11. package/ios/Frameworks/{PubkyMobile.xcframework/ios-arm64/libpubkymobile.a → PubkyCore.xcframework/ios-arm64/libpubkycore.a} +0 -0
  12. package/ios/Frameworks/{PubkyMobile.xcframework → PubkyCore.xcframework}/ios-arm64-simulator/Headers/module.modulemap +2 -2
  13. package/ios/Frameworks/PubkyCore.xcframework/ios-arm64-simulator/Headers/pubkycoreFFI.h +297 -0
  14. package/ios/Frameworks/{PubkyMobile.xcframework/ios-arm64-simulator/libpubkymobile.a → PubkyCore.xcframework/ios-arm64-simulator/libpubkycore.a} +0 -0
  15. package/ios/Pubky-Bridging-Header.h +1 -0
  16. package/ios/Pubky.mm +16 -1
  17. package/ios/Pubky.swift +64 -1
  18. package/ios/{pubkymobile.swift → pubkycore.swift} +354 -37
  19. package/lib/commonjs/index.js +45 -0
  20. package/lib/commonjs/index.js.map +1 -1
  21. package/lib/module/index.js +42 -1
  22. package/lib/module/index.js.map +1 -1
  23. package/lib/typescript/commonjs/src/index.d.ts +16 -9
  24. package/lib/typescript/commonjs/src/index.d.ts.map +1 -1
  25. package/lib/typescript/module/src/index.d.ts +16 -9
  26. package/lib/typescript/module/src/index.d.ts.map +1 -1
  27. package/package.json +12 -7
  28. package/react-native-pubky.podspec +1 -1
  29. package/src/index.tsx +62 -9
  30. package/android/src/main/java/uniffi/pubkymobile/pubkymobile.kt +0 -862
  31. package/android/src/main/jniLibs/arm64-v8a/libpubkymobile.so +0 -0
  32. package/android/src/main/jniLibs/armeabi-v7a/libpubkymobile.so +0 -0
  33. package/android/src/main/jniLibs/x86/libpubkymobile.so +0 -0
  34. package/android/src/main/jniLibs/x86_64/libpubkymobile.so +0 -0
  35. package/ios/Frameworks/PubkyMobile.xcframework/ios-arm64/Headers/mobileFFI.h +0 -188
  36. package/ios/Frameworks/PubkyMobile.xcframework/ios-arm64/Headers/pubkymobileFFI.h +0 -264
  37. package/ios/Frameworks/PubkyMobile.xcframework/ios-arm64/libmobile.a +0 -0
  38. package/ios/Frameworks/PubkyMobile.xcframework/ios-arm64-simulator/Headers/mobileFFI.h +0 -188
  39. package/ios/Frameworks/PubkyMobile.xcframework/ios-arm64-simulator/Headers/pubkymobileFFI.h +0 -264
  40. package/ios/Frameworks/PubkyMobile.xcframework/ios-arm64-simulator/libmobile.a +0 -0
@@ -0,0 +1,1327 @@
1
+ // This file was autogenerated by some hot garbage in the `uniffi` crate.
2
+ // Trust me, you don't want to mess with it!
3
+
4
+ @file:Suppress("NAME_SHADOWING")
5
+
6
+ package uniffi.pubkycore;
7
+
8
+ // Common helper code.
9
+ //
10
+ // Ideally this would live in a separate .kt file where it can be unittested etc
11
+ // in isolation, and perhaps even published as a re-useable package.
12
+ //
13
+ // However, it's important that the details of how this helper code works (e.g. the
14
+ // way that different builtin types are passed across the FFI) exactly match what's
15
+ // expected by the Rust code on the other side of the interface. In practice right
16
+ // now that means coming from the exact some version of `uniffi` that was used to
17
+ // compile the Rust component. The easiest way to ensure this is to bundle the Kotlin
18
+ // helpers directly inline like we're doing here.
19
+
20
+ import com.sun.jna.Library
21
+ import com.sun.jna.IntegerType
22
+ import com.sun.jna.Native
23
+ import com.sun.jna.Pointer
24
+ import com.sun.jna.Structure
25
+ import com.sun.jna.Callback
26
+ import com.sun.jna.ptr.*
27
+ import java.nio.ByteBuffer
28
+ import java.nio.ByteOrder
29
+ import java.nio.CharBuffer
30
+ import java.nio.charset.CodingErrorAction
31
+ import java.util.concurrent.ConcurrentHashMap
32
+ import java.util.concurrent.atomic.AtomicBoolean
33
+ import java.util.concurrent.atomic.AtomicLong
34
+ import java.util.concurrent.locks.ReentrantLock
35
+ import kotlin.concurrent.withLock
36
+
37
+ // This is a helper for safely working with byte buffers returned from the Rust code.
38
+ // A rust-owned buffer is represented by its capacity, its current length, and a
39
+ // pointer to the underlying data.
40
+
41
+ @Structure.FieldOrder("capacity", "len", "data")
42
+ open class RustBuffer : Structure() {
43
+ @JvmField var capacity: Int = 0
44
+ @JvmField var len: Int = 0
45
+ @JvmField var data: Pointer? = null
46
+
47
+ class ByValue: RustBuffer(), Structure.ByValue
48
+ class ByReference: RustBuffer(), Structure.ByReference
49
+
50
+ companion object {
51
+ internal fun alloc(size: Int = 0) = rustCall() { status ->
52
+ _UniFFILib.INSTANCE.ffi_pubkycore_rustbuffer_alloc(size, status)
53
+ }.also {
54
+ if(it.data == null) {
55
+ throw RuntimeException("RustBuffer.alloc() returned null data pointer (size=${size})")
56
+ }
57
+ }
58
+
59
+ internal fun create(capacity: Int, len: Int, data: Pointer?): RustBuffer.ByValue {
60
+ var buf = RustBuffer.ByValue()
61
+ buf.capacity = capacity
62
+ buf.len = len
63
+ buf.data = data
64
+ return buf
65
+ }
66
+
67
+ internal fun free(buf: RustBuffer.ByValue) = rustCall() { status ->
68
+ _UniFFILib.INSTANCE.ffi_pubkycore_rustbuffer_free(buf, status)
69
+ }
70
+ }
71
+
72
+ @Suppress("TooGenericExceptionThrown")
73
+ fun asByteBuffer() =
74
+ this.data?.getByteBuffer(0, this.len.toLong())?.also {
75
+ it.order(ByteOrder.BIG_ENDIAN)
76
+ }
77
+ }
78
+
79
+ /**
80
+ * The equivalent of the `*mut RustBuffer` type.
81
+ * Required for callbacks taking in an out pointer.
82
+ *
83
+ * Size is the sum of all values in the struct.
84
+ */
85
+ class RustBufferByReference : ByReference(16) {
86
+ /**
87
+ * Set the pointed-to `RustBuffer` to the given value.
88
+ */
89
+ fun setValue(value: RustBuffer.ByValue) {
90
+ // NOTE: The offsets are as they are in the C-like struct.
91
+ val pointer = getPointer()
92
+ pointer.setInt(0, value.capacity)
93
+ pointer.setInt(4, value.len)
94
+ pointer.setPointer(8, value.data)
95
+ }
96
+
97
+ /**
98
+ * Get a `RustBuffer.ByValue` from this reference.
99
+ */
100
+ fun getValue(): RustBuffer.ByValue {
101
+ val pointer = getPointer()
102
+ val value = RustBuffer.ByValue()
103
+ value.writeField("capacity", pointer.getInt(0))
104
+ value.writeField("len", pointer.getInt(4))
105
+ value.writeField("data", pointer.getPointer(8))
106
+
107
+ return value
108
+ }
109
+ }
110
+
111
+ // This is a helper for safely passing byte references into the rust code.
112
+ // It's not actually used at the moment, because there aren't many things that you
113
+ // can take a direct pointer to in the JVM, and if we're going to copy something
114
+ // then we might as well copy it into a `RustBuffer`. But it's here for API
115
+ // completeness.
116
+
117
+ @Structure.FieldOrder("len", "data")
118
+ open class ForeignBytes : Structure() {
119
+ @JvmField var len: Int = 0
120
+ @JvmField var data: Pointer? = null
121
+
122
+ class ByValue : ForeignBytes(), Structure.ByValue
123
+ }
124
+ // The FfiConverter interface handles converter types to and from the FFI
125
+ //
126
+ // All implementing objects should be public to support external types. When a
127
+ // type is external we need to import it's FfiConverter.
128
+ public interface FfiConverter<KotlinType, FfiType> {
129
+ // Convert an FFI type to a Kotlin type
130
+ fun lift(value: FfiType): KotlinType
131
+
132
+ // Convert an Kotlin type to an FFI type
133
+ fun lower(value: KotlinType): FfiType
134
+
135
+ // Read a Kotlin type from a `ByteBuffer`
136
+ fun read(buf: ByteBuffer): KotlinType
137
+
138
+ // Calculate bytes to allocate when creating a `RustBuffer`
139
+ //
140
+ // This must return at least as many bytes as the write() function will
141
+ // write. It can return more bytes than needed, for example when writing
142
+ // Strings we can't know the exact bytes needed until we the UTF-8
143
+ // encoding, so we pessimistically allocate the largest size possible (3
144
+ // bytes per codepoint). Allocating extra bytes is not really a big deal
145
+ // because the `RustBuffer` is short-lived.
146
+ fun allocationSize(value: KotlinType): Int
147
+
148
+ // Write a Kotlin type to a `ByteBuffer`
149
+ fun write(value: KotlinType, buf: ByteBuffer)
150
+
151
+ // Lower a value into a `RustBuffer`
152
+ //
153
+ // This method lowers a value into a `RustBuffer` rather than the normal
154
+ // FfiType. It's used by the callback interface code. Callback interface
155
+ // returns are always serialized into a `RustBuffer` regardless of their
156
+ // normal FFI type.
157
+ fun lowerIntoRustBuffer(value: KotlinType): RustBuffer.ByValue {
158
+ val rbuf = RustBuffer.alloc(allocationSize(value))
159
+ try {
160
+ val bbuf = rbuf.data!!.getByteBuffer(0, rbuf.capacity.toLong()).also {
161
+ it.order(ByteOrder.BIG_ENDIAN)
162
+ }
163
+ write(value, bbuf)
164
+ rbuf.writeField("len", bbuf.position())
165
+ return rbuf
166
+ } catch (e: Throwable) {
167
+ RustBuffer.free(rbuf)
168
+ throw e
169
+ }
170
+ }
171
+
172
+ // Lift a value from a `RustBuffer`.
173
+ //
174
+ // This here mostly because of the symmetry with `lowerIntoRustBuffer()`.
175
+ // It's currently only used by the `FfiConverterRustBuffer` class below.
176
+ fun liftFromRustBuffer(rbuf: RustBuffer.ByValue): KotlinType {
177
+ val byteBuf = rbuf.asByteBuffer()!!
178
+ try {
179
+ val item = read(byteBuf)
180
+ if (byteBuf.hasRemaining()) {
181
+ throw RuntimeException("junk remaining in buffer after lifting, something is very wrong!!")
182
+ }
183
+ return item
184
+ } finally {
185
+ RustBuffer.free(rbuf)
186
+ }
187
+ }
188
+ }
189
+
190
+ // FfiConverter that uses `RustBuffer` as the FfiType
191
+ public interface FfiConverterRustBuffer<KotlinType>: FfiConverter<KotlinType, RustBuffer.ByValue> {
192
+ override fun lift(value: RustBuffer.ByValue) = liftFromRustBuffer(value)
193
+ override fun lower(value: KotlinType) = lowerIntoRustBuffer(value)
194
+ }
195
+ // A handful of classes and functions to support the generated data structures.
196
+ // This would be a good candidate for isolating in its own ffi-support lib.
197
+ // Error runtime.
198
+ @Structure.FieldOrder("code", "error_buf")
199
+ internal open class RustCallStatus : Structure() {
200
+ @JvmField var code: Byte = 0
201
+ @JvmField var error_buf: RustBuffer.ByValue = RustBuffer.ByValue()
202
+
203
+ class ByValue: RustCallStatus(), Structure.ByValue
204
+
205
+ fun isSuccess(): Boolean {
206
+ return code == 0.toByte()
207
+ }
208
+
209
+ fun isError(): Boolean {
210
+ return code == 1.toByte()
211
+ }
212
+
213
+ fun isPanic(): Boolean {
214
+ return code == 2.toByte()
215
+ }
216
+ }
217
+
218
+ class InternalException(message: String) : Exception(message)
219
+
220
+ // Each top-level error class has a companion object that can lift the error from the call status's rust buffer
221
+ interface CallStatusErrorHandler<E> {
222
+ fun lift(error_buf: RustBuffer.ByValue): E;
223
+ }
224
+
225
+ // Helpers for calling Rust
226
+ // In practice we usually need to be synchronized to call this safely, so it doesn't
227
+ // synchronize itself
228
+
229
+ // Call a rust function that returns a Result<>. Pass in the Error class companion that corresponds to the Err
230
+ private inline fun <U, E: Exception> rustCallWithError(errorHandler: CallStatusErrorHandler<E>, callback: (RustCallStatus) -> U): U {
231
+ var status = RustCallStatus();
232
+ val return_value = callback(status)
233
+ checkCallStatus(errorHandler, status)
234
+ return return_value
235
+ }
236
+
237
+ // Check RustCallStatus and throw an error if the call wasn't successful
238
+ private fun<E: Exception> checkCallStatus(errorHandler: CallStatusErrorHandler<E>, status: RustCallStatus) {
239
+ if (status.isSuccess()) {
240
+ return
241
+ } else if (status.isError()) {
242
+ throw errorHandler.lift(status.error_buf)
243
+ } else if (status.isPanic()) {
244
+ // when the rust code sees a panic, it tries to construct a rustbuffer
245
+ // with the message. but if that code panics, then it just sends back
246
+ // an empty buffer.
247
+ if (status.error_buf.len > 0) {
248
+ throw InternalException(FfiConverterString.lift(status.error_buf))
249
+ } else {
250
+ throw InternalException("Rust panic")
251
+ }
252
+ } else {
253
+ throw InternalException("Unknown rust call status: $status.code")
254
+ }
255
+ }
256
+
257
+ // CallStatusErrorHandler implementation for times when we don't expect a CALL_ERROR
258
+ object NullCallStatusErrorHandler: CallStatusErrorHandler<InternalException> {
259
+ override fun lift(error_buf: RustBuffer.ByValue): InternalException {
260
+ RustBuffer.free(error_buf)
261
+ return InternalException("Unexpected CALL_ERROR")
262
+ }
263
+ }
264
+
265
+ // Call a rust function that returns a plain value
266
+ private inline fun <U> rustCall(callback: (RustCallStatus) -> U): U {
267
+ return rustCallWithError(NullCallStatusErrorHandler, callback);
268
+ }
269
+
270
+ // IntegerType that matches Rust's `usize` / C's `size_t`
271
+ public class USize(value: Long = 0) : IntegerType(Native.SIZE_T_SIZE, value, true) {
272
+ // This is needed to fill in the gaps of IntegerType's implementation of Number for Kotlin.
273
+ override fun toByte() = toInt().toByte()
274
+ // Needed until https://youtrack.jetbrains.com/issue/KT-47902 is fixed.
275
+ @Deprecated("`toInt().toChar()` is deprecated")
276
+ override fun toChar() = toInt().toChar()
277
+ override fun toShort() = toInt().toShort()
278
+
279
+ fun writeToBuffer(buf: ByteBuffer) {
280
+ // Make sure we always write usize integers using native byte-order, since they may be
281
+ // casted to pointer values
282
+ buf.order(ByteOrder.nativeOrder())
283
+ try {
284
+ when (Native.SIZE_T_SIZE) {
285
+ 4 -> buf.putInt(toInt())
286
+ 8 -> buf.putLong(toLong())
287
+ else -> throw RuntimeException("Invalid SIZE_T_SIZE: ${Native.SIZE_T_SIZE}")
288
+ }
289
+ } finally {
290
+ buf.order(ByteOrder.BIG_ENDIAN)
291
+ }
292
+ }
293
+
294
+ companion object {
295
+ val size: Int
296
+ get() = Native.SIZE_T_SIZE
297
+
298
+ fun readFromBuffer(buf: ByteBuffer) : USize {
299
+ // Make sure we always read usize integers using native byte-order, since they may be
300
+ // casted from pointer values
301
+ buf.order(ByteOrder.nativeOrder())
302
+ try {
303
+ return when (Native.SIZE_T_SIZE) {
304
+ 4 -> USize(buf.getInt().toLong())
305
+ 8 -> USize(buf.getLong())
306
+ else -> throw RuntimeException("Invalid SIZE_T_SIZE: ${Native.SIZE_T_SIZE}")
307
+ }
308
+ } finally {
309
+ buf.order(ByteOrder.BIG_ENDIAN)
310
+ }
311
+ }
312
+ }
313
+ }
314
+
315
+
316
+ // Map handles to objects
317
+ //
318
+ // This is used when the Rust code expects an opaque pointer to represent some foreign object.
319
+ // Normally we would pass a pointer to the object, but JNA doesn't support getting a pointer from an
320
+ // object reference , nor does it support leaking a reference to Rust.
321
+ //
322
+ // Instead, this class maps USize values to objects so that we can pass a pointer-sized type to
323
+ // Rust when it needs an opaque pointer.
324
+ //
325
+ // TODO: refactor callbacks to use this class
326
+ internal class UniFfiHandleMap<T: Any> {
327
+ private val map = ConcurrentHashMap<USize, T>()
328
+ // Use AtomicInteger for our counter, since we may be on a 32-bit system. 4 billion possible
329
+ // values seems like enough. If somehow we generate 4 billion handles, then this will wrap
330
+ // around back to zero and we can assume the first handle generated will have been dropped by
331
+ // then.
332
+ private val counter = java.util.concurrent.atomic.AtomicInteger(0)
333
+
334
+ val size: Int
335
+ get() = map.size
336
+
337
+ fun insert(obj: T): USize {
338
+ val handle = USize(counter.getAndAdd(1).toLong())
339
+ map.put(handle, obj)
340
+ return handle
341
+ }
342
+
343
+ fun get(handle: USize): T? {
344
+ return map.get(handle)
345
+ }
346
+
347
+ fun remove(handle: USize): T? {
348
+ return map.remove(handle)
349
+ }
350
+ }
351
+
352
+ // FFI type for Rust future continuations
353
+ internal interface UniFffiRustFutureContinuationCallbackType : com.sun.jna.Callback {
354
+ fun callback(continuationHandle: USize, pollResult: Short);
355
+ }
356
+
357
+ // Contains loading, initialization code,
358
+ // and the FFI Function declarations in a com.sun.jna.Library.
359
+ @Synchronized
360
+ private fun findLibraryName(componentName: String): String {
361
+ val libOverride = System.getProperty("uniffi.component.$componentName.libraryOverride")
362
+ if (libOverride != null) {
363
+ return libOverride
364
+ }
365
+ return "pubkycore"
366
+ }
367
+
368
+ private inline fun <reified Lib : Library> loadIndirect(
369
+ componentName: String
370
+ ): Lib {
371
+ return Native.load<Lib>(findLibraryName(componentName), Lib::class.java)
372
+ }
373
+
374
+ // A JNA Library to expose the extern-C FFI definitions.
375
+ // This is an implementation detail which will be called internally by the public API.
376
+
377
+ internal interface _UniFFILib : Library {
378
+ companion object {
379
+ internal val INSTANCE: _UniFFILib by lazy {
380
+ loadIndirect<_UniFFILib>(componentName = "pubkycore")
381
+ .also { lib: _UniFFILib ->
382
+ uniffiCheckContractApiVersion(lib)
383
+ uniffiCheckApiChecksums(lib)
384
+ FfiConverterTypeEventListener.register(lib)
385
+ }
386
+ }
387
+ }
388
+
389
+ fun uniffi_pubkycore_fn_free_eventnotifier(`ptr`: Pointer,_uniffi_out_err: RustCallStatus,
390
+ ): Unit
391
+ fun uniffi_pubkycore_fn_init_callback_eventlistener(`callbackStub`: ForeignCallback,_uniffi_out_err: RustCallStatus,
392
+ ): Unit
393
+ fun uniffi_pubkycore_fn_func_auth(`url`: RustBuffer.ByValue,`secretKey`: RustBuffer.ByValue,_uniffi_out_err: RustCallStatus,
394
+ ): RustBuffer.ByValue
395
+ fun uniffi_pubkycore_fn_func_create_recovery_file(`secretKey`: RustBuffer.ByValue,`passphrase`: RustBuffer.ByValue,_uniffi_out_err: RustCallStatus,
396
+ ): RustBuffer.ByValue
397
+ fun uniffi_pubkycore_fn_func_decrypt_recovery_file(`recoveryFile`: RustBuffer.ByValue,`passphrase`: RustBuffer.ByValue,_uniffi_out_err: RustCallStatus,
398
+ ): RustBuffer.ByValue
399
+ fun uniffi_pubkycore_fn_func_delete_file(`url`: RustBuffer.ByValue,_uniffi_out_err: RustCallStatus,
400
+ ): RustBuffer.ByValue
401
+ fun uniffi_pubkycore_fn_func_generate_secret_key(_uniffi_out_err: RustCallStatus,
402
+ ): RustBuffer.ByValue
403
+ fun uniffi_pubkycore_fn_func_get(`url`: RustBuffer.ByValue,_uniffi_out_err: RustCallStatus,
404
+ ): RustBuffer.ByValue
405
+ fun uniffi_pubkycore_fn_func_get_public_key_from_secret_key(`secretKey`: RustBuffer.ByValue,_uniffi_out_err: RustCallStatus,
406
+ ): RustBuffer.ByValue
407
+ fun uniffi_pubkycore_fn_func_list(`url`: RustBuffer.ByValue,_uniffi_out_err: RustCallStatus,
408
+ ): RustBuffer.ByValue
409
+ fun uniffi_pubkycore_fn_func_parse_auth_url(`url`: RustBuffer.ByValue,_uniffi_out_err: RustCallStatus,
410
+ ): RustBuffer.ByValue
411
+ fun uniffi_pubkycore_fn_func_publish(`recordName`: RustBuffer.ByValue,`recordContent`: RustBuffer.ByValue,`secretKey`: RustBuffer.ByValue,_uniffi_out_err: RustCallStatus,
412
+ ): RustBuffer.ByValue
413
+ fun uniffi_pubkycore_fn_func_publish_https(`recordName`: RustBuffer.ByValue,`target`: RustBuffer.ByValue,`secretKey`: RustBuffer.ByValue,_uniffi_out_err: RustCallStatus,
414
+ ): RustBuffer.ByValue
415
+ fun uniffi_pubkycore_fn_func_put(`url`: RustBuffer.ByValue,`content`: RustBuffer.ByValue,_uniffi_out_err: RustCallStatus,
416
+ ): RustBuffer.ByValue
417
+ fun uniffi_pubkycore_fn_func_remove_event_listener(_uniffi_out_err: RustCallStatus,
418
+ ): Unit
419
+ fun uniffi_pubkycore_fn_func_resolve(`publicKey`: RustBuffer.ByValue,_uniffi_out_err: RustCallStatus,
420
+ ): RustBuffer.ByValue
421
+ fun uniffi_pubkycore_fn_func_resolve_https(`publicKey`: RustBuffer.ByValue,_uniffi_out_err: RustCallStatus,
422
+ ): RustBuffer.ByValue
423
+ fun uniffi_pubkycore_fn_func_session(`pubky`: RustBuffer.ByValue,_uniffi_out_err: RustCallStatus,
424
+ ): RustBuffer.ByValue
425
+ fun uniffi_pubkycore_fn_func_set_event_listener(`listener`: Long,_uniffi_out_err: RustCallStatus,
426
+ ): Unit
427
+ fun uniffi_pubkycore_fn_func_sign_in(`secretKey`: RustBuffer.ByValue,_uniffi_out_err: RustCallStatus,
428
+ ): RustBuffer.ByValue
429
+ fun uniffi_pubkycore_fn_func_sign_out(`secretKey`: RustBuffer.ByValue,_uniffi_out_err: RustCallStatus,
430
+ ): RustBuffer.ByValue
431
+ fun uniffi_pubkycore_fn_func_sign_up(`secretKey`: RustBuffer.ByValue,`homeserver`: RustBuffer.ByValue,_uniffi_out_err: RustCallStatus,
432
+ ): RustBuffer.ByValue
433
+ fun uniffi_pubkycore_fn_func_switch_network(`useTestnet`: Byte,_uniffi_out_err: RustCallStatus,
434
+ ): RustBuffer.ByValue
435
+ fun ffi_pubkycore_rustbuffer_alloc(`size`: Int,_uniffi_out_err: RustCallStatus,
436
+ ): RustBuffer.ByValue
437
+ fun ffi_pubkycore_rustbuffer_from_bytes(`bytes`: ForeignBytes.ByValue,_uniffi_out_err: RustCallStatus,
438
+ ): RustBuffer.ByValue
439
+ fun ffi_pubkycore_rustbuffer_free(`buf`: RustBuffer.ByValue,_uniffi_out_err: RustCallStatus,
440
+ ): Unit
441
+ fun ffi_pubkycore_rustbuffer_reserve(`buf`: RustBuffer.ByValue,`additional`: Int,_uniffi_out_err: RustCallStatus,
442
+ ): RustBuffer.ByValue
443
+ fun ffi_pubkycore_rust_future_continuation_callback_set(`callback`: UniFffiRustFutureContinuationCallbackType,
444
+ ): Unit
445
+ fun ffi_pubkycore_rust_future_poll_u8(`handle`: Pointer,`uniffiCallback`: USize,
446
+ ): Unit
447
+ fun ffi_pubkycore_rust_future_cancel_u8(`handle`: Pointer,
448
+ ): Unit
449
+ fun ffi_pubkycore_rust_future_free_u8(`handle`: Pointer,
450
+ ): Unit
451
+ fun ffi_pubkycore_rust_future_complete_u8(`handle`: Pointer,_uniffi_out_err: RustCallStatus,
452
+ ): Byte
453
+ fun ffi_pubkycore_rust_future_poll_i8(`handle`: Pointer,`uniffiCallback`: USize,
454
+ ): Unit
455
+ fun ffi_pubkycore_rust_future_cancel_i8(`handle`: Pointer,
456
+ ): Unit
457
+ fun ffi_pubkycore_rust_future_free_i8(`handle`: Pointer,
458
+ ): Unit
459
+ fun ffi_pubkycore_rust_future_complete_i8(`handle`: Pointer,_uniffi_out_err: RustCallStatus,
460
+ ): Byte
461
+ fun ffi_pubkycore_rust_future_poll_u16(`handle`: Pointer,`uniffiCallback`: USize,
462
+ ): Unit
463
+ fun ffi_pubkycore_rust_future_cancel_u16(`handle`: Pointer,
464
+ ): Unit
465
+ fun ffi_pubkycore_rust_future_free_u16(`handle`: Pointer,
466
+ ): Unit
467
+ fun ffi_pubkycore_rust_future_complete_u16(`handle`: Pointer,_uniffi_out_err: RustCallStatus,
468
+ ): Short
469
+ fun ffi_pubkycore_rust_future_poll_i16(`handle`: Pointer,`uniffiCallback`: USize,
470
+ ): Unit
471
+ fun ffi_pubkycore_rust_future_cancel_i16(`handle`: Pointer,
472
+ ): Unit
473
+ fun ffi_pubkycore_rust_future_free_i16(`handle`: Pointer,
474
+ ): Unit
475
+ fun ffi_pubkycore_rust_future_complete_i16(`handle`: Pointer,_uniffi_out_err: RustCallStatus,
476
+ ): Short
477
+ fun ffi_pubkycore_rust_future_poll_u32(`handle`: Pointer,`uniffiCallback`: USize,
478
+ ): Unit
479
+ fun ffi_pubkycore_rust_future_cancel_u32(`handle`: Pointer,
480
+ ): Unit
481
+ fun ffi_pubkycore_rust_future_free_u32(`handle`: Pointer,
482
+ ): Unit
483
+ fun ffi_pubkycore_rust_future_complete_u32(`handle`: Pointer,_uniffi_out_err: RustCallStatus,
484
+ ): Int
485
+ fun ffi_pubkycore_rust_future_poll_i32(`handle`: Pointer,`uniffiCallback`: USize,
486
+ ): Unit
487
+ fun ffi_pubkycore_rust_future_cancel_i32(`handle`: Pointer,
488
+ ): Unit
489
+ fun ffi_pubkycore_rust_future_free_i32(`handle`: Pointer,
490
+ ): Unit
491
+ fun ffi_pubkycore_rust_future_complete_i32(`handle`: Pointer,_uniffi_out_err: RustCallStatus,
492
+ ): Int
493
+ fun ffi_pubkycore_rust_future_poll_u64(`handle`: Pointer,`uniffiCallback`: USize,
494
+ ): Unit
495
+ fun ffi_pubkycore_rust_future_cancel_u64(`handle`: Pointer,
496
+ ): Unit
497
+ fun ffi_pubkycore_rust_future_free_u64(`handle`: Pointer,
498
+ ): Unit
499
+ fun ffi_pubkycore_rust_future_complete_u64(`handle`: Pointer,_uniffi_out_err: RustCallStatus,
500
+ ): Long
501
+ fun ffi_pubkycore_rust_future_poll_i64(`handle`: Pointer,`uniffiCallback`: USize,
502
+ ): Unit
503
+ fun ffi_pubkycore_rust_future_cancel_i64(`handle`: Pointer,
504
+ ): Unit
505
+ fun ffi_pubkycore_rust_future_free_i64(`handle`: Pointer,
506
+ ): Unit
507
+ fun ffi_pubkycore_rust_future_complete_i64(`handle`: Pointer,_uniffi_out_err: RustCallStatus,
508
+ ): Long
509
+ fun ffi_pubkycore_rust_future_poll_f32(`handle`: Pointer,`uniffiCallback`: USize,
510
+ ): Unit
511
+ fun ffi_pubkycore_rust_future_cancel_f32(`handle`: Pointer,
512
+ ): Unit
513
+ fun ffi_pubkycore_rust_future_free_f32(`handle`: Pointer,
514
+ ): Unit
515
+ fun ffi_pubkycore_rust_future_complete_f32(`handle`: Pointer,_uniffi_out_err: RustCallStatus,
516
+ ): Float
517
+ fun ffi_pubkycore_rust_future_poll_f64(`handle`: Pointer,`uniffiCallback`: USize,
518
+ ): Unit
519
+ fun ffi_pubkycore_rust_future_cancel_f64(`handle`: Pointer,
520
+ ): Unit
521
+ fun ffi_pubkycore_rust_future_free_f64(`handle`: Pointer,
522
+ ): Unit
523
+ fun ffi_pubkycore_rust_future_complete_f64(`handle`: Pointer,_uniffi_out_err: RustCallStatus,
524
+ ): Double
525
+ fun ffi_pubkycore_rust_future_poll_pointer(`handle`: Pointer,`uniffiCallback`: USize,
526
+ ): Unit
527
+ fun ffi_pubkycore_rust_future_cancel_pointer(`handle`: Pointer,
528
+ ): Unit
529
+ fun ffi_pubkycore_rust_future_free_pointer(`handle`: Pointer,
530
+ ): Unit
531
+ fun ffi_pubkycore_rust_future_complete_pointer(`handle`: Pointer,_uniffi_out_err: RustCallStatus,
532
+ ): Pointer
533
+ fun ffi_pubkycore_rust_future_poll_rust_buffer(`handle`: Pointer,`uniffiCallback`: USize,
534
+ ): Unit
535
+ fun ffi_pubkycore_rust_future_cancel_rust_buffer(`handle`: Pointer,
536
+ ): Unit
537
+ fun ffi_pubkycore_rust_future_free_rust_buffer(`handle`: Pointer,
538
+ ): Unit
539
+ fun ffi_pubkycore_rust_future_complete_rust_buffer(`handle`: Pointer,_uniffi_out_err: RustCallStatus,
540
+ ): RustBuffer.ByValue
541
+ fun ffi_pubkycore_rust_future_poll_void(`handle`: Pointer,`uniffiCallback`: USize,
542
+ ): Unit
543
+ fun ffi_pubkycore_rust_future_cancel_void(`handle`: Pointer,
544
+ ): Unit
545
+ fun ffi_pubkycore_rust_future_free_void(`handle`: Pointer,
546
+ ): Unit
547
+ fun ffi_pubkycore_rust_future_complete_void(`handle`: Pointer,_uniffi_out_err: RustCallStatus,
548
+ ): Unit
549
+ fun uniffi_pubkycore_checksum_func_auth(
550
+ ): Short
551
+ fun uniffi_pubkycore_checksum_func_create_recovery_file(
552
+ ): Short
553
+ fun uniffi_pubkycore_checksum_func_decrypt_recovery_file(
554
+ ): Short
555
+ fun uniffi_pubkycore_checksum_func_delete_file(
556
+ ): Short
557
+ fun uniffi_pubkycore_checksum_func_generate_secret_key(
558
+ ): Short
559
+ fun uniffi_pubkycore_checksum_func_get(
560
+ ): Short
561
+ fun uniffi_pubkycore_checksum_func_get_public_key_from_secret_key(
562
+ ): Short
563
+ fun uniffi_pubkycore_checksum_func_list(
564
+ ): Short
565
+ fun uniffi_pubkycore_checksum_func_parse_auth_url(
566
+ ): Short
567
+ fun uniffi_pubkycore_checksum_func_publish(
568
+ ): Short
569
+ fun uniffi_pubkycore_checksum_func_publish_https(
570
+ ): Short
571
+ fun uniffi_pubkycore_checksum_func_put(
572
+ ): Short
573
+ fun uniffi_pubkycore_checksum_func_remove_event_listener(
574
+ ): Short
575
+ fun uniffi_pubkycore_checksum_func_resolve(
576
+ ): Short
577
+ fun uniffi_pubkycore_checksum_func_resolve_https(
578
+ ): Short
579
+ fun uniffi_pubkycore_checksum_func_session(
580
+ ): Short
581
+ fun uniffi_pubkycore_checksum_func_set_event_listener(
582
+ ): Short
583
+ fun uniffi_pubkycore_checksum_func_sign_in(
584
+ ): Short
585
+ fun uniffi_pubkycore_checksum_func_sign_out(
586
+ ): Short
587
+ fun uniffi_pubkycore_checksum_func_sign_up(
588
+ ): Short
589
+ fun uniffi_pubkycore_checksum_func_switch_network(
590
+ ): Short
591
+ fun uniffi_pubkycore_checksum_method_eventlistener_on_event_occurred(
592
+ ): Short
593
+ fun ffi_pubkycore_uniffi_contract_version(
594
+ ): Int
595
+
596
+ }
597
+
598
+ private fun uniffiCheckContractApiVersion(lib: _UniFFILib) {
599
+ // Get the bindings contract version from our ComponentInterface
600
+ val bindings_contract_version = 24
601
+ // Get the scaffolding contract version by calling the into the dylib
602
+ val scaffolding_contract_version = lib.ffi_pubkycore_uniffi_contract_version()
603
+ if (bindings_contract_version != scaffolding_contract_version) {
604
+ throw RuntimeException("UniFFI contract version mismatch: try cleaning and rebuilding your project")
605
+ }
606
+ }
607
+
608
+ @Suppress("UNUSED_PARAMETER")
609
+ private fun uniffiCheckApiChecksums(lib: _UniFFILib) {
610
+ if (lib.uniffi_pubkycore_checksum_func_auth() != 51826.toShort()) {
611
+ throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project")
612
+ }
613
+ if (lib.uniffi_pubkycore_checksum_func_create_recovery_file() != 48846.toShort()) {
614
+ throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project")
615
+ }
616
+ if (lib.uniffi_pubkycore_checksum_func_decrypt_recovery_file() != 26407.toShort()) {
617
+ throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project")
618
+ }
619
+ if (lib.uniffi_pubkycore_checksum_func_delete_file() != 9063.toShort()) {
620
+ throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project")
621
+ }
622
+ if (lib.uniffi_pubkycore_checksum_func_generate_secret_key() != 12800.toShort()) {
623
+ throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project")
624
+ }
625
+ if (lib.uniffi_pubkycore_checksum_func_get() != 6591.toShort()) {
626
+ throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project")
627
+ }
628
+ if (lib.uniffi_pubkycore_checksum_func_get_public_key_from_secret_key() != 40316.toShort()) {
629
+ throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project")
630
+ }
631
+ if (lib.uniffi_pubkycore_checksum_func_list() != 43198.toShort()) {
632
+ throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project")
633
+ }
634
+ if (lib.uniffi_pubkycore_checksum_func_parse_auth_url() != 27379.toShort()) {
635
+ throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project")
636
+ }
637
+ if (lib.uniffi_pubkycore_checksum_func_publish() != 48989.toShort()) {
638
+ throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project")
639
+ }
640
+ if (lib.uniffi_pubkycore_checksum_func_publish_https() != 5614.toShort()) {
641
+ throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project")
642
+ }
643
+ if (lib.uniffi_pubkycore_checksum_func_put() != 48150.toShort()) {
644
+ throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project")
645
+ }
646
+ if (lib.uniffi_pubkycore_checksum_func_remove_event_listener() != 23534.toShort()) {
647
+ throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project")
648
+ }
649
+ if (lib.uniffi_pubkycore_checksum_func_resolve() != 34317.toShort()) {
650
+ throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project")
651
+ }
652
+ if (lib.uniffi_pubkycore_checksum_func_resolve_https() != 17266.toShort()) {
653
+ throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project")
654
+ }
655
+ if (lib.uniffi_pubkycore_checksum_func_session() != 59795.toShort()) {
656
+ throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project")
657
+ }
658
+ if (lib.uniffi_pubkycore_checksum_func_set_event_listener() != 60071.toShort()) {
659
+ throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project")
660
+ }
661
+ if (lib.uniffi_pubkycore_checksum_func_sign_in() != 21584.toShort()) {
662
+ throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project")
663
+ }
664
+ if (lib.uniffi_pubkycore_checksum_func_sign_out() != 34903.toShort()) {
665
+ throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project")
666
+ }
667
+ if (lib.uniffi_pubkycore_checksum_func_sign_up() != 37999.toShort()) {
668
+ throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project")
669
+ }
670
+ if (lib.uniffi_pubkycore_checksum_func_switch_network() != 64215.toShort()) {
671
+ throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project")
672
+ }
673
+ if (lib.uniffi_pubkycore_checksum_method_eventlistener_on_event_occurred() != 11531.toShort()) {
674
+ throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project")
675
+ }
676
+ }
677
+
678
+ // Async support
679
+
680
+ // Public interface members begin here.
681
+
682
+
683
+ public object FfiConverterBoolean: FfiConverter<Boolean, Byte> {
684
+ override fun lift(value: Byte): Boolean {
685
+ return value.toInt() != 0
686
+ }
687
+
688
+ override fun read(buf: ByteBuffer): Boolean {
689
+ return lift(buf.get())
690
+ }
691
+
692
+ override fun lower(value: Boolean): Byte {
693
+ return if (value) 1.toByte() else 0.toByte()
694
+ }
695
+
696
+ override fun allocationSize(value: Boolean) = 1
697
+
698
+ override fun write(value: Boolean, buf: ByteBuffer) {
699
+ buf.put(lower(value))
700
+ }
701
+ }
702
+
703
+ public object FfiConverterString: FfiConverter<String, RustBuffer.ByValue> {
704
+ // Note: we don't inherit from FfiConverterRustBuffer, because we use a
705
+ // special encoding when lowering/lifting. We can use `RustBuffer.len` to
706
+ // store our length and avoid writing it out to the buffer.
707
+ override fun lift(value: RustBuffer.ByValue): String {
708
+ try {
709
+ val byteArr = ByteArray(value.len)
710
+ value.asByteBuffer()!!.get(byteArr)
711
+ return byteArr.toString(Charsets.UTF_8)
712
+ } finally {
713
+ RustBuffer.free(value)
714
+ }
715
+ }
716
+
717
+ override fun read(buf: ByteBuffer): String {
718
+ val len = buf.getInt()
719
+ val byteArr = ByteArray(len)
720
+ buf.get(byteArr)
721
+ return byteArr.toString(Charsets.UTF_8)
722
+ }
723
+
724
+ fun toUtf8(value: String): ByteBuffer {
725
+ // Make sure we don't have invalid UTF-16, check for lone surrogates.
726
+ return Charsets.UTF_8.newEncoder().run {
727
+ onMalformedInput(CodingErrorAction.REPORT)
728
+ encode(CharBuffer.wrap(value))
729
+ }
730
+ }
731
+
732
+ override fun lower(value: String): RustBuffer.ByValue {
733
+ val byteBuf = toUtf8(value)
734
+ // Ideally we'd pass these bytes to `ffi_bytebuffer_from_bytes`, but doing so would require us
735
+ // to copy them into a JNA `Memory`. So we might as well directly copy them into a `RustBuffer`.
736
+ val rbuf = RustBuffer.alloc(byteBuf.limit())
737
+ rbuf.asByteBuffer()!!.put(byteBuf)
738
+ return rbuf
739
+ }
740
+
741
+ // We aren't sure exactly how many bytes our string will be once it's UTF-8
742
+ // encoded. Allocate 3 bytes per UTF-16 code unit which will always be
743
+ // enough.
744
+ override fun allocationSize(value: String): Int {
745
+ val sizeForLength = 4
746
+ val sizeForString = value.length * 3
747
+ return sizeForLength + sizeForString
748
+ }
749
+
750
+ override fun write(value: String, buf: ByteBuffer) {
751
+ val byteBuf = toUtf8(value)
752
+ buf.putInt(byteBuf.limit())
753
+ buf.put(byteBuf)
754
+ }
755
+ }
756
+
757
+
758
+ // Interface implemented by anything that can contain an object reference.
759
+ //
760
+ // Such types expose a `destroy()` method that must be called to cleanly
761
+ // dispose of the contained objects. Failure to call this method may result
762
+ // in memory leaks.
763
+ //
764
+ // The easiest way to ensure this method is called is to use the `.use`
765
+ // helper method to execute a block and destroy the object at the end.
766
+ interface Disposable {
767
+ fun destroy()
768
+ companion object {
769
+ fun destroy(vararg args: Any?) {
770
+ args.filterIsInstance<Disposable>()
771
+ .forEach(Disposable::destroy)
772
+ }
773
+ }
774
+ }
775
+
776
+ inline fun <T : Disposable?, R> T.use(block: (T) -> R) =
777
+ try {
778
+ block(this)
779
+ } finally {
780
+ try {
781
+ // N.B. our implementation is on the nullable type `Disposable?`.
782
+ this?.destroy()
783
+ } catch (e: Throwable) {
784
+ // swallow
785
+ }
786
+ }
787
+
788
+ // The base class for all UniFFI Object types.
789
+ //
790
+ // This class provides core operations for working with the Rust `Arc<T>` pointer to
791
+ // the live Rust struct on the other side of the FFI.
792
+ //
793
+ // There's some subtlety here, because we have to be careful not to operate on a Rust
794
+ // struct after it has been dropped, and because we must expose a public API for freeing
795
+ // the Kotlin wrapper object in lieu of reliable finalizers. The core requirements are:
796
+ //
797
+ // * Each `FFIObject` instance holds an opaque pointer to the underlying Rust struct.
798
+ // Method calls need to read this pointer from the object's state and pass it in to
799
+ // the Rust FFI.
800
+ //
801
+ // * When an `FFIObject` is no longer needed, its pointer should be passed to a
802
+ // special destructor function provided by the Rust FFI, which will drop the
803
+ // underlying Rust struct.
804
+ //
805
+ // * Given an `FFIObject` instance, calling code is expected to call the special
806
+ // `destroy` method in order to free it after use, either by calling it explicitly
807
+ // or by using a higher-level helper like the `use` method. Failing to do so will
808
+ // leak the underlying Rust struct.
809
+ //
810
+ // * We can't assume that calling code will do the right thing, and must be prepared
811
+ // to handle Kotlin method calls executing concurrently with or even after a call to
812
+ // `destroy`, and to handle multiple (possibly concurrent!) calls to `destroy`.
813
+ //
814
+ // * We must never allow Rust code to operate on the underlying Rust struct after
815
+ // the destructor has been called, and must never call the destructor more than once.
816
+ // Doing so may trigger memory unsafety.
817
+ //
818
+ // If we try to implement this with mutual exclusion on access to the pointer, there is the
819
+ // possibility of a race between a method call and a concurrent call to `destroy`:
820
+ //
821
+ // * Thread A starts a method call, reads the value of the pointer, but is interrupted
822
+ // before it can pass the pointer over the FFI to Rust.
823
+ // * Thread B calls `destroy` and frees the underlying Rust struct.
824
+ // * Thread A resumes, passing the already-read pointer value to Rust and triggering
825
+ // a use-after-free.
826
+ //
827
+ // One possible solution would be to use a `ReadWriteLock`, with each method call taking
828
+ // a read lock (and thus allowed to run concurrently) and the special `destroy` method
829
+ // taking a write lock (and thus blocking on live method calls). However, we aim not to
830
+ // generate methods with any hidden blocking semantics, and a `destroy` method that might
831
+ // block if called incorrectly seems to meet that bar.
832
+ //
833
+ // So, we achieve our goals by giving each `FFIObject` an associated `AtomicLong` counter to track
834
+ // the number of in-flight method calls, and an `AtomicBoolean` flag to indicate whether `destroy`
835
+ // has been called. These are updated according to the following rules:
836
+ //
837
+ // * The initial value of the counter is 1, indicating a live object with no in-flight calls.
838
+ // The initial value for the flag is false.
839
+ //
840
+ // * At the start of each method call, we atomically check the counter.
841
+ // If it is 0 then the underlying Rust struct has already been destroyed and the call is aborted.
842
+ // If it is nonzero them we atomically increment it by 1 and proceed with the method call.
843
+ //
844
+ // * At the end of each method call, we atomically decrement and check the counter.
845
+ // If it has reached zero then we destroy the underlying Rust struct.
846
+ //
847
+ // * When `destroy` is called, we atomically flip the flag from false to true.
848
+ // If the flag was already true we silently fail.
849
+ // Otherwise we atomically decrement and check the counter.
850
+ // If it has reached zero then we destroy the underlying Rust struct.
851
+ //
852
+ // Astute readers may observe that this all sounds very similar to the way that Rust's `Arc<T>` works,
853
+ // and indeed it is, with the addition of a flag to guard against multiple calls to `destroy`.
854
+ //
855
+ // The overall effect is that the underlying Rust struct is destroyed only when `destroy` has been
856
+ // called *and* all in-flight method calls have completed, avoiding violating any of the expectations
857
+ // of the underlying Rust code.
858
+ //
859
+ // In the future we may be able to replace some of this with automatic finalization logic, such as using
860
+ // the new "Cleaner" functionaility in Java 9. The above scheme has been designed to work even if `destroy` is
861
+ // invoked by garbage-collection machinery rather than by calling code (which by the way, it's apparently also
862
+ // possible for the JVM to finalize an object while there is an in-flight call to one of its methods [1],
863
+ // so there would still be some complexity here).
864
+ //
865
+ // Sigh...all of this for want of a robust finalization mechanism.
866
+ //
867
+ // [1] https://stackoverflow.com/questions/24376768/can-java-finalize-an-object-when-it-is-still-in-scope/24380219
868
+ //
869
+ abstract class FFIObject(
870
+ protected val pointer: Pointer
871
+ ): Disposable, AutoCloseable {
872
+
873
+ private val wasDestroyed = AtomicBoolean(false)
874
+ private val callCounter = AtomicLong(1)
875
+
876
+ open protected fun freeRustArcPtr() {
877
+ // To be overridden in subclasses.
878
+ }
879
+
880
+ override fun destroy() {
881
+ // Only allow a single call to this method.
882
+ // TODO: maybe we should log a warning if called more than once?
883
+ if (this.wasDestroyed.compareAndSet(false, true)) {
884
+ // This decrement always matches the initial count of 1 given at creation time.
885
+ if (this.callCounter.decrementAndGet() == 0L) {
886
+ this.freeRustArcPtr()
887
+ }
888
+ }
889
+ }
890
+
891
+ @Synchronized
892
+ override fun close() {
893
+ this.destroy()
894
+ }
895
+
896
+ internal inline fun <R> callWithPointer(block: (ptr: Pointer) -> R): R {
897
+ // Check and increment the call counter, to keep the object alive.
898
+ // This needs a compare-and-set retry loop in case of concurrent updates.
899
+ do {
900
+ val c = this.callCounter.get()
901
+ if (c == 0L) {
902
+ throw IllegalStateException("${this.javaClass.simpleName} object has already been destroyed")
903
+ }
904
+ if (c == Long.MAX_VALUE) {
905
+ throw IllegalStateException("${this.javaClass.simpleName} call counter would overflow")
906
+ }
907
+ } while (! this.callCounter.compareAndSet(c, c + 1L))
908
+ // Now we can safely do the method call without the pointer being freed concurrently.
909
+ try {
910
+ return block(this.pointer)
911
+ } finally {
912
+ // This decrement always matches the increment we performed above.
913
+ if (this.callCounter.decrementAndGet() == 0L) {
914
+ this.freeRustArcPtr()
915
+ }
916
+ }
917
+ }
918
+ }
919
+
920
+ public interface EventNotifierInterface {
921
+
922
+ companion object
923
+ }
924
+
925
+ class EventNotifier(
926
+ pointer: Pointer
927
+ ) : FFIObject(pointer), EventNotifierInterface {
928
+
929
+ /**
930
+ * Disconnect the object from the underlying Rust object.
931
+ *
932
+ * It can be called more than once, but once called, interacting with the object
933
+ * causes an `IllegalStateException`.
934
+ *
935
+ * Clients **must** call this method once done with the object, or cause a memory leak.
936
+ */
937
+ override protected fun freeRustArcPtr() {
938
+ rustCall() { status ->
939
+ _UniFFILib.INSTANCE.uniffi_pubkycore_fn_free_eventnotifier(this.pointer, status)
940
+ }
941
+ }
942
+
943
+
944
+
945
+
946
+ companion object
947
+
948
+ }
949
+
950
+ public object FfiConverterTypeEventNotifier: FfiConverter<EventNotifier, Pointer> {
951
+ override fun lower(value: EventNotifier): Pointer = value.callWithPointer { it }
952
+
953
+ override fun lift(value: Pointer): EventNotifier {
954
+ return EventNotifier(value)
955
+ }
956
+
957
+ override fun read(buf: ByteBuffer): EventNotifier {
958
+ // The Rust code always writes pointers as 8 bytes, and will
959
+ // fail to compile if they don't fit.
960
+ return lift(Pointer(buf.getLong()))
961
+ }
962
+
963
+ override fun allocationSize(value: EventNotifier) = 8
964
+
965
+ override fun write(value: EventNotifier, buf: ByteBuffer) {
966
+ // The Rust code always expects pointers written as 8 bytes,
967
+ // and will fail to compile if they don't fit.
968
+ buf.putLong(Pointer.nativeValue(lower(value)))
969
+ }
970
+ }
971
+
972
+
973
+
974
+
975
+ internal typealias Handle = Long
976
+ internal class ConcurrentHandleMap<T>(
977
+ private val leftMap: MutableMap<Handle, T> = mutableMapOf(),
978
+ private val rightMap: MutableMap<T, Handle> = mutableMapOf()
979
+ ) {
980
+ private val lock = java.util.concurrent.locks.ReentrantLock()
981
+ private val currentHandle = AtomicLong(0L)
982
+ private val stride = 1L
983
+
984
+ fun insert(obj: T): Handle =
985
+ lock.withLock {
986
+ rightMap[obj] ?:
987
+ currentHandle.getAndAdd(stride)
988
+ .also { handle ->
989
+ leftMap[handle] = obj
990
+ rightMap[obj] = handle
991
+ }
992
+ }
993
+
994
+ fun get(handle: Handle) = lock.withLock {
995
+ leftMap[handle]
996
+ }
997
+
998
+ fun delete(handle: Handle) {
999
+ this.remove(handle)
1000
+ }
1001
+
1002
+ fun remove(handle: Handle): T? =
1003
+ lock.withLock {
1004
+ leftMap.remove(handle)?.let { obj ->
1005
+ rightMap.remove(obj)
1006
+ obj
1007
+ }
1008
+ }
1009
+ }
1010
+
1011
+ interface ForeignCallback : com.sun.jna.Callback {
1012
+ public fun callback(handle: Handle, method: Int, argsData: Pointer, argsLen: Int, outBuf: RustBufferByReference): Int
1013
+ }
1014
+
1015
+ // Magic number for the Rust proxy to call using the same mechanism as every other method,
1016
+ // to free the callback once it's dropped by Rust.
1017
+ internal const val IDX_CALLBACK_FREE = 0
1018
+ // Callback return codes
1019
+ internal const val UNIFFI_CALLBACK_SUCCESS = 0
1020
+ internal const val UNIFFI_CALLBACK_ERROR = 1
1021
+ internal const val UNIFFI_CALLBACK_UNEXPECTED_ERROR = 2
1022
+
1023
+ public abstract class FfiConverterCallbackInterface<CallbackInterface>(
1024
+ protected val foreignCallback: ForeignCallback
1025
+ ): FfiConverter<CallbackInterface, Handle> {
1026
+ private val handleMap = ConcurrentHandleMap<CallbackInterface>()
1027
+
1028
+ // Registers the foreign callback with the Rust side.
1029
+ // This method is generated for each callback interface.
1030
+ internal abstract fun register(lib: _UniFFILib)
1031
+
1032
+ fun drop(handle: Handle): RustBuffer.ByValue {
1033
+ return handleMap.remove(handle).let { RustBuffer.ByValue() }
1034
+ }
1035
+
1036
+ override fun lift(value: Handle): CallbackInterface {
1037
+ return handleMap.get(value) ?: throw InternalException("No callback in handlemap; this is a Uniffi bug")
1038
+ }
1039
+
1040
+ override fun read(buf: ByteBuffer) = lift(buf.getLong())
1041
+
1042
+ override fun lower(value: CallbackInterface) =
1043
+ handleMap.insert(value).also {
1044
+ assert(handleMap.get(it) === value) { "Handle map is not returning the object we just placed there. This is a bug in the HandleMap." }
1045
+ }
1046
+
1047
+ override fun allocationSize(value: CallbackInterface) = 8
1048
+
1049
+ override fun write(value: CallbackInterface, buf: ByteBuffer) {
1050
+ buf.putLong(lower(value))
1051
+ }
1052
+ }
1053
+
1054
+ // Declaration and FfiConverters for EventListener Callback Interface
1055
+
1056
+ public interface EventListener {
1057
+ fun `onEventOccurred`(`eventData`: String)
1058
+
1059
+ companion object
1060
+ }
1061
+
1062
+ // The ForeignCallback that is passed to Rust.
1063
+ internal class ForeignCallbackTypeEventListener : ForeignCallback {
1064
+ @Suppress("TooGenericExceptionCaught")
1065
+ override fun callback(handle: Handle, method: Int, argsData: Pointer, argsLen: Int, outBuf: RustBufferByReference): Int {
1066
+ val cb = FfiConverterTypeEventListener.lift(handle)
1067
+ return when (method) {
1068
+ IDX_CALLBACK_FREE -> {
1069
+ FfiConverterTypeEventListener.drop(handle)
1070
+ // Successful return
1071
+ // See docs of ForeignCallback in `uniffi_core/src/ffi/foreigncallbacks.rs`
1072
+ UNIFFI_CALLBACK_SUCCESS
1073
+ }
1074
+ 1 -> {
1075
+ // Call the method, write to outBuf and return a status code
1076
+ // See docs of ForeignCallback in `uniffi_core/src/ffi/foreigncallbacks.rs` for info
1077
+ try {
1078
+ this.`invokeOnEventOccurred`(cb, argsData, argsLen, outBuf)
1079
+ } catch (e: Throwable) {
1080
+ // Unexpected error
1081
+ try {
1082
+ // Try to serialize the error into a string
1083
+ outBuf.setValue(FfiConverterString.lower(e.toString()))
1084
+ } catch (e: Throwable) {
1085
+ // If that fails, then it's time to give up and just return
1086
+ }
1087
+ UNIFFI_CALLBACK_UNEXPECTED_ERROR
1088
+ }
1089
+ }
1090
+
1091
+ else -> {
1092
+ // An unexpected error happened.
1093
+ // See docs of ForeignCallback in `uniffi_core/src/ffi/foreigncallbacks.rs`
1094
+ try {
1095
+ // Try to serialize the error into a string
1096
+ outBuf.setValue(FfiConverterString.lower("Invalid Callback index"))
1097
+ } catch (e: Throwable) {
1098
+ // If that fails, then it's time to give up and just return
1099
+ }
1100
+ UNIFFI_CALLBACK_UNEXPECTED_ERROR
1101
+ }
1102
+ }
1103
+ }
1104
+
1105
+
1106
+ @Suppress("UNUSED_PARAMETER")
1107
+ private fun `invokeOnEventOccurred`(kotlinCallbackInterface: EventListener, argsData: Pointer, argsLen: Int, outBuf: RustBufferByReference): Int {
1108
+ val argsBuf = argsData.getByteBuffer(0, argsLen.toLong()).also {
1109
+ it.order(ByteOrder.BIG_ENDIAN)
1110
+ }
1111
+ fun makeCall() : Int {
1112
+ kotlinCallbackInterface.`onEventOccurred`(
1113
+ FfiConverterString.read(argsBuf)
1114
+ )
1115
+ return UNIFFI_CALLBACK_SUCCESS
1116
+ }
1117
+ fun makeCallAndHandleError() : Int = makeCall()
1118
+
1119
+ return makeCallAndHandleError()
1120
+ }
1121
+
1122
+ }
1123
+
1124
+ // The ffiConverter which transforms the Callbacks in to Handles to pass to Rust.
1125
+ public object FfiConverterTypeEventListener: FfiConverterCallbackInterface<EventListener>(
1126
+ foreignCallback = ForeignCallbackTypeEventListener()
1127
+ ) {
1128
+ override fun register(lib: _UniFFILib) {
1129
+ rustCall() { status ->
1130
+ lib.uniffi_pubkycore_fn_init_callback_eventlistener(this.foreignCallback, status)
1131
+ }
1132
+ }
1133
+ }
1134
+
1135
+
1136
+
1137
+
1138
+ public object FfiConverterSequenceString: FfiConverterRustBuffer<List<String>> {
1139
+ override fun read(buf: ByteBuffer): List<String> {
1140
+ val len = buf.getInt()
1141
+ return List<String>(len) {
1142
+ FfiConverterString.read(buf)
1143
+ }
1144
+ }
1145
+
1146
+ override fun allocationSize(value: List<String>): Int {
1147
+ val sizeForLength = 4
1148
+ val sizeForItems = value.map { FfiConverterString.allocationSize(it) }.sum()
1149
+ return sizeForLength + sizeForItems
1150
+ }
1151
+
1152
+ override fun write(value: List<String>, buf: ByteBuffer) {
1153
+ buf.putInt(value.size)
1154
+ value.forEach {
1155
+ FfiConverterString.write(it, buf)
1156
+ }
1157
+ }
1158
+ }
1159
+
1160
+ fun `auth`(`url`: String, `secretKey`: String): List<String> {
1161
+ return FfiConverterSequenceString.lift(
1162
+ rustCall() { _status ->
1163
+ _UniFFILib.INSTANCE.uniffi_pubkycore_fn_func_auth(FfiConverterString.lower(`url`),FfiConverterString.lower(`secretKey`),_status)
1164
+ })
1165
+ }
1166
+
1167
+
1168
+ fun `createRecoveryFile`(`secretKey`: String, `passphrase`: String): List<String> {
1169
+ return FfiConverterSequenceString.lift(
1170
+ rustCall() { _status ->
1171
+ _UniFFILib.INSTANCE.uniffi_pubkycore_fn_func_create_recovery_file(FfiConverterString.lower(`secretKey`),FfiConverterString.lower(`passphrase`),_status)
1172
+ })
1173
+ }
1174
+
1175
+
1176
+ fun `decryptRecoveryFile`(`recoveryFile`: String, `passphrase`: String): List<String> {
1177
+ return FfiConverterSequenceString.lift(
1178
+ rustCall() { _status ->
1179
+ _UniFFILib.INSTANCE.uniffi_pubkycore_fn_func_decrypt_recovery_file(FfiConverterString.lower(`recoveryFile`),FfiConverterString.lower(`passphrase`),_status)
1180
+ })
1181
+ }
1182
+
1183
+
1184
+ fun `deleteFile`(`url`: String): List<String> {
1185
+ return FfiConverterSequenceString.lift(
1186
+ rustCall() { _status ->
1187
+ _UniFFILib.INSTANCE.uniffi_pubkycore_fn_func_delete_file(FfiConverterString.lower(`url`),_status)
1188
+ })
1189
+ }
1190
+
1191
+
1192
+ fun `generateSecretKey`(): List<String> {
1193
+ return FfiConverterSequenceString.lift(
1194
+ rustCall() { _status ->
1195
+ _UniFFILib.INSTANCE.uniffi_pubkycore_fn_func_generate_secret_key(_status)
1196
+ })
1197
+ }
1198
+
1199
+
1200
+ fun `get`(`url`: String): List<String> {
1201
+ return FfiConverterSequenceString.lift(
1202
+ rustCall() { _status ->
1203
+ _UniFFILib.INSTANCE.uniffi_pubkycore_fn_func_get(FfiConverterString.lower(`url`),_status)
1204
+ })
1205
+ }
1206
+
1207
+
1208
+ fun `getPublicKeyFromSecretKey`(`secretKey`: String): List<String> {
1209
+ return FfiConverterSequenceString.lift(
1210
+ rustCall() { _status ->
1211
+ _UniFFILib.INSTANCE.uniffi_pubkycore_fn_func_get_public_key_from_secret_key(FfiConverterString.lower(`secretKey`),_status)
1212
+ })
1213
+ }
1214
+
1215
+
1216
+ fun `list`(`url`: String): List<String> {
1217
+ return FfiConverterSequenceString.lift(
1218
+ rustCall() { _status ->
1219
+ _UniFFILib.INSTANCE.uniffi_pubkycore_fn_func_list(FfiConverterString.lower(`url`),_status)
1220
+ })
1221
+ }
1222
+
1223
+
1224
+ fun `parseAuthUrl`(`url`: String): List<String> {
1225
+ return FfiConverterSequenceString.lift(
1226
+ rustCall() { _status ->
1227
+ _UniFFILib.INSTANCE.uniffi_pubkycore_fn_func_parse_auth_url(FfiConverterString.lower(`url`),_status)
1228
+ })
1229
+ }
1230
+
1231
+
1232
+ fun `publish`(`recordName`: String, `recordContent`: String, `secretKey`: String): List<String> {
1233
+ return FfiConverterSequenceString.lift(
1234
+ rustCall() { _status ->
1235
+ _UniFFILib.INSTANCE.uniffi_pubkycore_fn_func_publish(FfiConverterString.lower(`recordName`),FfiConverterString.lower(`recordContent`),FfiConverterString.lower(`secretKey`),_status)
1236
+ })
1237
+ }
1238
+
1239
+
1240
+ fun `publishHttps`(`recordName`: String, `target`: String, `secretKey`: String): List<String> {
1241
+ return FfiConverterSequenceString.lift(
1242
+ rustCall() { _status ->
1243
+ _UniFFILib.INSTANCE.uniffi_pubkycore_fn_func_publish_https(FfiConverterString.lower(`recordName`),FfiConverterString.lower(`target`),FfiConverterString.lower(`secretKey`),_status)
1244
+ })
1245
+ }
1246
+
1247
+
1248
+ fun `put`(`url`: String, `content`: String): List<String> {
1249
+ return FfiConverterSequenceString.lift(
1250
+ rustCall() { _status ->
1251
+ _UniFFILib.INSTANCE.uniffi_pubkycore_fn_func_put(FfiConverterString.lower(`url`),FfiConverterString.lower(`content`),_status)
1252
+ })
1253
+ }
1254
+
1255
+
1256
+ fun `removeEventListener`() =
1257
+
1258
+ rustCall() { _status ->
1259
+ _UniFFILib.INSTANCE.uniffi_pubkycore_fn_func_remove_event_listener(_status)
1260
+ }
1261
+
1262
+
1263
+
1264
+ fun `resolve`(`publicKey`: String): List<String> {
1265
+ return FfiConverterSequenceString.lift(
1266
+ rustCall() { _status ->
1267
+ _UniFFILib.INSTANCE.uniffi_pubkycore_fn_func_resolve(FfiConverterString.lower(`publicKey`),_status)
1268
+ })
1269
+ }
1270
+
1271
+
1272
+ fun `resolveHttps`(`publicKey`: String): List<String> {
1273
+ return FfiConverterSequenceString.lift(
1274
+ rustCall() { _status ->
1275
+ _UniFFILib.INSTANCE.uniffi_pubkycore_fn_func_resolve_https(FfiConverterString.lower(`publicKey`),_status)
1276
+ })
1277
+ }
1278
+
1279
+
1280
+ fun `session`(`pubky`: String): List<String> {
1281
+ return FfiConverterSequenceString.lift(
1282
+ rustCall() { _status ->
1283
+ _UniFFILib.INSTANCE.uniffi_pubkycore_fn_func_session(FfiConverterString.lower(`pubky`),_status)
1284
+ })
1285
+ }
1286
+
1287
+
1288
+ fun `setEventListener`(`listener`: EventListener) =
1289
+
1290
+ rustCall() { _status ->
1291
+ _UniFFILib.INSTANCE.uniffi_pubkycore_fn_func_set_event_listener(FfiConverterTypeEventListener.lower(`listener`),_status)
1292
+ }
1293
+
1294
+
1295
+
1296
+ fun `signIn`(`secretKey`: String): List<String> {
1297
+ return FfiConverterSequenceString.lift(
1298
+ rustCall() { _status ->
1299
+ _UniFFILib.INSTANCE.uniffi_pubkycore_fn_func_sign_in(FfiConverterString.lower(`secretKey`),_status)
1300
+ })
1301
+ }
1302
+
1303
+
1304
+ fun `signOut`(`secretKey`: String): List<String> {
1305
+ return FfiConverterSequenceString.lift(
1306
+ rustCall() { _status ->
1307
+ _UniFFILib.INSTANCE.uniffi_pubkycore_fn_func_sign_out(FfiConverterString.lower(`secretKey`),_status)
1308
+ })
1309
+ }
1310
+
1311
+
1312
+ fun `signUp`(`secretKey`: String, `homeserver`: String): List<String> {
1313
+ return FfiConverterSequenceString.lift(
1314
+ rustCall() { _status ->
1315
+ _UniFFILib.INSTANCE.uniffi_pubkycore_fn_func_sign_up(FfiConverterString.lower(`secretKey`),FfiConverterString.lower(`homeserver`),_status)
1316
+ })
1317
+ }
1318
+
1319
+
1320
+ fun `switchNetwork`(`useTestnet`: Boolean): List<String> {
1321
+ return FfiConverterSequenceString.lift(
1322
+ rustCall() { _status ->
1323
+ _UniFFILib.INSTANCE.uniffi_pubkycore_fn_func_switch_network(FfiConverterBoolean.lower(`useTestnet`),_status)
1324
+ })
1325
+ }
1326
+
1327
+