internal static unsafe class {{ closure.bridge_name }}
{
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
{%- if closure.method.native_return_type.is_bool() %}
[return: MarshalAs(UnmanagedType.I1)]
{%- endif %}
internal delegate {{ closure.method.native_return_type }} NativeInvoke({{ closure.method.native_params }});
private static readonly NativeInvoke InvokeDelegate = Invoke;
internal static Scope Pin({{ closure.public_name }} impl_) => new(impl_);
internal sealed class Scope : IDisposable
{
private GCHandle _handle;
private bool _disposed;
internal Scope({{ closure.public_name }} impl_)
{
_handle = GCHandle.Alloc(impl_);
Function = InvokeDelegate;
Context = GCHandle.ToIntPtr(_handle);
}
internal NativeInvoke Function { get; }
internal IntPtr Context { get; }
public void Dispose()
{
if (_disposed) return;
_disposed = true;
if (_handle.IsAllocated) _handle.Free();
}
}
private static {{ closure.method.native_return_type }} Invoke({{ closure.method.native_params }})
{
var impl_ = ({{ closure.public_name }})((GCHandle)context).Target!;
{%- for param in closure.method.bridge_params %}
{%- match param %}
{%- when CSharpCallbackBridgeParamPlan::Direct with { public_param, native_param, decoded_arg, proxy_arg } %}
{%- when CSharpCallbackBridgeParamPlan::WireEncoded with { public_param, native_ptr_param, native_len_param, reader_local, decoded_arg, writer, pin_local, ptr_local } %}
var {{ reader_local }} = new WireReader({{ native_ptr_param.name }}, {{ native_len_param.name }});
{%- endmatch %}
{%- endfor %}
{%- match closure.method.invoke %}
{%- when CSharpClosureInvokePlan::Void with { decoded_args } %}
impl_({{ decoded_args }});
{%- when CSharpClosureInvokePlan::Direct with { decoded_args, native_value_expr } %}
var __boltffiValue = impl_({{ decoded_args }});
return {{ native_value_expr }};
{%- when CSharpClosureInvokePlan::Encoded with { is_result, decoded_args, result_assignment, writer } %}
{%- if let Some(result_assignment) = result_assignment %}
BoltFFIResult<{{ result_assignment.result_type.ok_type }}, {{ result_assignment.result_type.err_type }}> __boltffiResult;
try
{
{%- match result_assignment.ok %}
{%- when CSharpCallbackResultOkPlan::Void with { receiver, method_name, args } %}
{{ receiver }}.{{ method_name }}({{ args }});
__boltffiResult = BoltFFIResult<{{ result_assignment.result_type.ok_type }}, {{ result_assignment.result_type.err_type }}>.Ok(default);
{%- when CSharpCallbackResultOkPlan::Value with { receiver, method_name, args } %}
__boltffiResult = BoltFFIResult<{{ result_assignment.result_type.ok_type }}, {{ result_assignment.result_type.err_type }}>.Ok({{ receiver }}.{{ method_name }}({{ args }}));
{%- endmatch %}
}
{%- match result_assignment.catch %}
{%- when Some with (catch_plan) %}
{%- match catch_plan %}
{%- when CSharpCallbackResultCatchPlan::TypedException with { exception_type } %}
catch ({{ exception_type }} __boltffiException)
{
__boltffiResult = BoltFFIResult<{{ result_assignment.result_type.ok_type }}, {{ result_assignment.result_type.err_type }}>.Err(__boltffiException.Error);
}
{%- when CSharpCallbackResultCatchPlan::ExceptionMessage %}
catch (Exception __boltffiException)
{
__boltffiResult = BoltFFIResult<{{ result_assignment.result_type.ok_type }}, {{ result_assignment.result_type.err_type }}>.Err(__boltffiException.Message);
}
{%- endmatch %}
{%- when None %}
catch
{
throw;
}
{%- endmatch %}
{%- else %}
var __boltffiValue = impl_({{ decoded_args }});
{%- endif %}
byte[] {{ writer.bytes_binding_name }};
using (var {{ writer.binding_name }} = new WireWriter({{ writer.size_expr }}))
{
{%- for stmt in writer.encode_stmts %}
{{ stmt }};
{%- endfor %}
{{ writer.bytes_binding_name }} = {{ writer.binding_name }}.ToArray();
}
return FfiBuf.FromBytes({{ writer.bytes_binding_name }});
{%- endmatch %}
}
}