{{ self::swift_doc_block(callback.doc, "") }}/// > 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 {{ callback.protocol_name }}: AnyObject {
{%- for method in callback.methods %}
{{ self::swift_doc_block(method.doc, " ") }} func {{ method.swift_name }}({% for param in method.params %}{{ param.label }}: {{ param.swift_type }}{% if !loop.last %}, {% endif %}{% endfor %}){% if method.is_async %} async{% endif %}{% if method.throws() %} throws{% endif %}{% if let Some(ret) = method.return_type() %} -> {{ ret }}{% endif %}
{%- endfor %}
}
private class {{ callback.wrapper_class }} {
let impl_: {{ callback.protocol_name }}
init(_ impl_: {{ callback.protocol_name }}) { self.impl_ = impl_ }
}
{% for method in callback.methods %}
{%- if method.is_async %}
private func _{{ callback.vtable_var }}_{{ method.swift_name }}(_ wrapper: {{ callback.wrapper_class }}, {% for param in method.params %}_ {{ param.label }}: {{ param.swift_type }}, {% endfor %}_ callback: {{ method.async_callback_c_type() }}, _ callbackData: UInt64) {
Task {
{%- if method.throws() %}
do {
{% if method.has_return() %}let result = {% endif %}try await wrapper.impl_.{{ method.swift_name }}({% for param in method.params %}{{ param.label }}: {{ param.label }}{% if !loop.last %}, {% endif %}{% endfor %})
{%- if method.has_return() %}
{%- if method.wire_encoded_return() %}
{%- if let Some(encoded) = method.wire_return_encode() %}
{{ encoded }}
{%- endif %}
boltffiInvokeWireCallback(callback, callbackData, encoded, FfiStatus(code: 0))
{%- else %}
callback?(callbackData, result, FfiStatus(code: 0))
{%- endif %}
{%- else %}
callback?(callbackData, FfiStatus(code: 0))
{%- endif %}
} catch {
{%- if let Some(err_type) = method.err_type() %}
{%- if let Some(err_encoded) = method.wire_err_encode() %}
guard let error = error as? {{ err_type }} else {
var errWriter = WireWriter()
errWriter.writeString(String(describing: error))
boltffiInvokeWireCallback(callback, callbackData, errWriter.finalize(), FfiStatus(code: 1))
return
}
{{ err_encoded }}
boltffiInvokeWireCallback(callback, callbackData, encoded, FfiStatus(code: 0))
{%- else %}
var errWriter = WireWriter()
errWriter.writeString(String(describing: error))
boltffiInvokeWireCallback(callback, callbackData, errWriter.finalize(), FfiStatus(code: 1))
{%- endif %}
{%- else %}
var errWriter = WireWriter()
errWriter.writeString(String(describing: error))
boltffiInvokeWireCallback(callback, callbackData, errWriter.finalize(), FfiStatus(code: 1))
{%- endif %}
}
{%- else %}
{% if method.has_return() %}let result = {% endif %}await wrapper.impl_.{{ method.swift_name }}({% for param in method.params %}{{ param.label }}: {{ param.label }}{% if !loop.last %}, {% endif %}{% endfor %})
{%- if method.has_return() %}
{%- if method.wire_encoded_return() %}
{%- if let Some(encoded) = method.wire_return_encode() %}
{{ encoded }}
{%- endif %}
boltffiInvokeWireCallback(callback, callbackData, encoded, FfiStatus(code: 0))
{%- else %}
callback?(callbackData, result, FfiStatus(code: 0))
{%- endif %}
{%- else %}
callback?(callbackData, FfiStatus(code: 0))
{%- endif %}
{%- endif %}
}
}
{%- endif %}
{%- endfor %}
private var {{ callback.vtable_var }}: {{ callback.vtable_type }} = {
{{ callback.vtable_type }}(
free: { handle in
guard handle != 0 else { return }
Unmanaged<{{ callback.wrapper_class }}>.fromOpaque(UnsafeRawPointer(bitPattern: UInt(handle))!).release()
},
clone: { handle in
guard handle != 0 else { return 0 }
let wrapper = Unmanaged<{{ callback.wrapper_class }}>.fromOpaque(UnsafeRawPointer(bitPattern: UInt(handle))!)
_ = wrapper.retain()
return handle
}{% for method in callback.methods %},
{{ method.ffi_name }}: { handle{% for param in method.params %}{% for arg in param.ffi_args %}, {{ arg }}{% endfor %}{% endfor %}{% if method.has_out_param %}{% if method.wire_encoded_return() %}, outPtr, outLen{% else %}, outPtr{% endif %}{% endif %}{% if !method.is_async %}, statusPtr{% endif %}{% if method.is_async %}, callback, callbackData{% endif %} in
guard handle != 0 else { {% if !method.is_async %}statusPtr?.pointee = FfiStatus(code: 1); {% endif %}return }
let wrapper = Unmanaged<{{ callback.wrapper_class }}>.fromOpaque(UnsafeRawPointer(bitPattern: UInt(handle))!).takeUnretainedValue()
{%- for param in method.params %}
{%- match param.decode_prelude %}{% when Some with (prelude) %}
{{ prelude }}
{%- when None %}{% endmatch %}
{%- endfor %}
{%- if method.is_async %}
_{{ callback.vtable_var }}_{{ method.swift_name }}(wrapper, {% for param in method.params %}{{ param.call_arg }}, {% endfor %}callback, callbackData)
{%- else %}
{% if method.has_return() %}let result = {% endif %}wrapper.impl_.{{ method.swift_name }}({% for param in method.params %}{{ param.label }}: {{ param.call_arg }}{% if !loop.last %}, {% endif %}{% endfor %})
{%- if method.has_out_param %}
{%- if method.wire_encoded_return() %}
{%- if let Some(encoded) = method.wire_return_encode() %}
{{ encoded }}
{%- endif %}
_ = encoded.withUnsafeBytes { bytes in
memcpy(outPtr!, bytes.baseAddress!, bytes.count)
}
outLen?.pointee = UInt(encoded.count)
{%- else %}
outPtr?.pointee = result
{%- endif %}
{%- endif %}
statusPtr?.pointee = FfiStatus(code: 0)
{%- endif %}
}{% endfor %}
)
}()
enum {{ callback.bridge_name }} {
private static let _register: Void = {
{{ callback.register_fn }}(&{{ callback.vtable_var }})
}()
static func create(_ impl: {{ callback.protocol_name }}) -> BoltFFICallbackHandle {
_ = _register
let wrapper = {{ callback.wrapper_class }}(impl)
let handle = UInt64(UInt(bitPattern: Unmanaged.passRetained(wrapper).toOpaque()))
return {{ callback.create_fn }}(handle)
}
}