---
source: boltffi_bindgen/src/render/swift/templates.rs
expression: render_callback(&callback)
---
/// > Warning: Callback methods may be invoked from any thread and the thread is not
/// > guaranteed to be the same between calls. Your implementation must be thread-safe.
/// > Dispatch to the main thread if updating UI.
public protocol AsyncHandler: AnyObject {
    func onComplete(result: String) async
}

private class AsyncHandlerWrapper {
    let impl_: AsyncHandler
    init(_ impl_: AsyncHandler) { self.impl_ = impl_ }
}


private func _asyncHandlerVtable_onComplete(_ wrapper: AsyncHandlerWrapper, _ result: String, _ callback: (@convention(c) (UInt64, FfiStatus) -> Void)?, _ callbackData: UInt64) {
    _Concurrency.Task {
        await wrapper.impl_.onComplete(result: result)
        callback?(callbackData, FfiStatus(code: 0))
    }
}

private var asyncHandlerVtable: AsyncHandlerVtable = {
    AsyncHandlerVtable(
        free: { handle in
            guard handle != 0 else { return }
            Unmanaged<AsyncHandlerWrapper>.fromOpaque(UnsafeRawPointer(bitPattern: UInt(handle))!).release()
        },
        clone: { handle in
            guard handle != 0 else { return 0 }
            let wrapper = Unmanaged<AsyncHandlerWrapper>.fromOpaque(UnsafeRawPointer(bitPattern: UInt(handle))!)
            _ = wrapper.retain()
            return handle
        },
        on_complete: { handle, resultPtr, resultLen, callback, callbackData in
            guard handle != 0 else { return }
            let wrapper = Unmanaged<AsyncHandlerWrapper>.fromOpaque(UnsafeRawPointer(bitPattern: UInt(handle))!).takeUnretainedValue()
            let result = String(decoding: UnsafeBufferPointer(start: resultPtr, count: Int(resultLen)), as: UTF8.self)
            _asyncHandlerVtable_onComplete(wrapper, result, callback, callbackData)
        }
    )
}()

enum AsyncHandlerBridge {
    private static let _register: Void = {
        boltffi_register_async_handler(&asyncHandlerVtable)
    }()

    static func create(_ impl: AsyncHandler) -> BoltFFICallbackHandle {
        _ = _register
        let wrapper = AsyncHandlerWrapper(impl)
        let handle = UInt64(UInt(bitPattern: Unmanaged.passRetained(wrapper).toOpaque()))
        return boltffi_create_async_handler(handle)
    }
}
