alef 0.25.37

Opinionated polyglot binding generator for Rust libraries
Documentation
  # GenServer for dispatching trait_call messages from Rust.
  defmodule {{ server_module }} do
    use GenServer

    def start_link(state) do
      GenServer.start_link(__MODULE__, state)
    end

    def init(state) do
      {:ok, state}
    end

    def handle_cast({:trait_call, method, args_json, reply_id}, registrations) do
      # Decode JSON args and dispatch to registered handler
      case decode_args_and_dispatch(method, args_json, registrations) do
        {:ok, response} ->
          Native.complete_trait_call(reply_id, response)

        {:error, reason} ->
          error_response = %{"error" => reason}
          Native.complete_trait_call(reply_id, error_response)
      end

      {:noreply, registrations}
    end


    defp decode_args_and_dispatch(method, args_json, registrations) do
      # Find handler entry for the method
      case find_handler(method, registrations) do
        nil ->
          {:error, "Handler not registered for method: #{method}"}

        {^method, _metadata, handler} ->
          # Decode JSON args (assumes handler accepts a single arg)
          case Jason.decode(args_json) do
            {:ok, args} ->
              # Call the registered handler with decoded args
              try do
                response = handler.(args)
                # Encode response to JSON
                case Jason.encode(response) do
                  {:ok, response_json} ->
                    {:ok, response_json}

                  {:error, reason} ->
                    {:error, "Failed to encode response: #{reason}"}
                end
              rescue
                e ->
                  {:error, "Handler raised exception: #{inspect(e)}"}
              end

            {:error, reason} ->
              {:error, "Failed to decode args: #{reason}"}
          end
      end
    end

    defp find_handler(_method, []), do: nil

    defp find_handler(target, [{name, _metadata, _handler} = entry | _rest]) when name == target do
      entry
    end

    defp find_handler(target, [_head | rest]) do
      find_handler(target, rest)
    end
  end