@synonymdev/react-native-pubky 0.8.0 → 0.9.1

Sign up to get free protection for your applications and to get access to all the features.
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
+