---
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 DataHandler: AnyObject {
    func onData(data: Data)
}

private class DataHandlerWrapper {
    let impl_: DataHandler
    init(_ impl_: DataHandler) { self.impl_ = impl_ }
}


private var dataHandlerVtable: DataHandlerVtable = {
    DataHandlerVtable(
        free: { handle in
            guard handle != 0 else { return }
            Unmanaged<DataHandlerWrapper>.fromOpaque(UnsafeRawPointer(bitPattern: UInt(handle))!).release()
        },
        clone: { handle in
            guard handle != 0 else { return 0 }
            let wrapper = Unmanaged<DataHandlerWrapper>.fromOpaque(UnsafeRawPointer(bitPattern: UInt(handle))!)
            _ = wrapper.retain()
            return handle
        },
        on_data: { handle, dataPtr, dataLen, statusPtr in
            guard handle != 0 else { statusPtr?.pointee = FfiStatus(code: 1); return }
            let wrapper = Unmanaged<DataHandlerWrapper>.fromOpaque(UnsafeRawPointer(bitPattern: UInt(handle))!).takeUnretainedValue()
            let data = Data(bytes: dataPtr!, count: Int(dataLen))
            wrapper.impl_.onData(data: data)
            statusPtr?.pointee = FfiStatus(code: 0)
        }
    )
}()

enum DataHandlerBridge {
    private static let _register: Void = {
        boltffi_register_data_handler(&dataHandlerVtable)
    }()

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