@doc false
defp do_visitor_receive_loop(visitor) do
receive do
{:visitor_callback, ref_id, callback_name, args} ->
result =
case Map.get(visitor, callback_name) do
nil -> "{{ default_result_wire_name }}"
fun -> apply_visitor_callback(fun, args)
end
{{ native_mod }}.visitor_reply(ref_id, result)
do_visitor_receive_loop(visitor)
{:ok, result} ->
{:ok, result}
{:error, reason} ->
{:error, reason}
after
30_000 ->
{:error, "visitor callback timeout after 30s"}
end
end
@doc false
defp apply_visitor_callback(fun, args) do
# `args` arrives as a native Erlang/Elixir map built on the Rust side (struct params as
# native maps, primitives as native terms) — no JSON envelope to decode.
result = fun.(args)
case result do
{% for variant in unit_result_variants %}
"{{ variant.wire_name }}" -> "{{ variant.wire_name }}"
{% if variant.atom_name %}
:{{ variant.atom_name }} -> "{{ variant.wire_name }}"
{% endif %}
{% endfor %}
{:custom, value} -> to_string(value)
binary when is_binary(binary) -> binary
_ -> "{{ default_result_wire_name }}"
end
end