diff options
Diffstat (limited to '')
-rw-r--r-- | third_party/rust/uniffi_bindgen/src/bindings/swift/templates/ForeignExecutorTemplate.swift | 69 |
1 files changed, 69 insertions, 0 deletions
diff --git a/third_party/rust/uniffi_bindgen/src/bindings/swift/templates/ForeignExecutorTemplate.swift b/third_party/rust/uniffi_bindgen/src/bindings/swift/templates/ForeignExecutorTemplate.swift new file mode 100644 index 0000000000..167e4c7546 --- /dev/null +++ b/third_party/rust/uniffi_bindgen/src/bindings/swift/templates/ForeignExecutorTemplate.swift @@ -0,0 +1,69 @@ +private let UNIFFI_RUST_TASK_CALLBACK_SUCCESS: Int8 = 0 +private let UNIFFI_RUST_TASK_CALLBACK_CANCELLED: Int8 = 1 +private let UNIFFI_FOREIGN_EXECUTOR_CALLBACK_SUCCESS: Int8 = 0 +private let UNIFFI_FOREIGN_EXECUTOR_CALLBACK_CANCELED: Int8 = 1 +private let UNIFFI_FOREIGN_EXECUTOR_CALLBACK_ERROR: Int8 = 2 + +// Encapsulates an executor that can run Rust tasks +// +// On Swift, `Task.detached` can handle this we just need to know what priority to send it. +public struct UniFfiForeignExecutor { + var priority: TaskPriority + + public init(priority: TaskPriority) { + self.priority = priority + } + + public init() { + self.priority = Task.currentPriority + } +} + +fileprivate struct FfiConverterForeignExecutor: FfiConverter { + typealias SwiftType = UniFfiForeignExecutor + // Rust uses a pointer to represent the FfiConverterForeignExecutor, but we only need a u8. + // let's use `Int`, which is equivalent to `size_t` + typealias FfiType = Int + + public static func lift(_ value: FfiType) throws -> SwiftType { + UniFfiForeignExecutor(priority: TaskPriority(rawValue: numericCast(value))) + } + public static func lower(_ value: SwiftType) -> FfiType { + numericCast(value.priority.rawValue) + } + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> SwiftType { + fatalError("FfiConverterForeignExecutor.read not implemented yet") + } + public static func write(_ value: SwiftType, into buf: inout [UInt8]) { + fatalError("FfiConverterForeignExecutor.read not implemented yet") + } +} + + +fileprivate func uniffiForeignExecutorCallback(executorHandle: Int, delayMs: UInt32, rustTask: UniFfiRustTaskCallback?, taskData: UnsafeRawPointer?) -> Int8 { + if let rustTask = rustTask { + let executor = try! FfiConverterForeignExecutor.lift(executorHandle) + Task.detached(priority: executor.priority) { + if delayMs != 0 { + let nanoseconds: UInt64 = numericCast(delayMs * 1000000) + try! await Task.sleep(nanoseconds: nanoseconds) + } + rustTask(taskData, UNIFFI_RUST_TASK_CALLBACK_SUCCESS) + } + return UNIFFI_FOREIGN_EXECUTOR_CALLBACK_SUCCESS + } else { + // When rustTask is null, we should drop the foreign executor. + // However, since its just a value type, we don't need to do anything here. + return UNIFFI_FOREIGN_EXECUTOR_CALLBACK_SUCCESS + } +} + +fileprivate func uniffiInitForeignExecutor() { + {%- match ci.ffi_foreign_executor_callback_set() %} + {%- when Some with (fn) %} + {{ fn.name() }}(uniffiForeignExecutorCallback) + {%- when None %} + {#- No foreign executor, we don't set anything #} + {% endmatch %} +} |