defmodule QuickBEAM.WASM.Server do
@moduledoc false
use GenServer
defstruct [:module_ref, :instance_ref]
def start_link(opts) do
{gen_opts, wasm_opts} = Keyword.split(opts, [:name])
GenServer.start_link(__MODULE__, wasm_opts, gen_opts)
end
@impl true
def init(opts) do
wasm_bytes = Keyword.fetch!(opts, :module)
stack_size = Keyword.get(opts, :stack_size, 65_536)
heap_size = Keyword.get(opts, :heap_size, 65_536)
with {:ok, mod_ref} <- QuickBEAM.Native.wasm_compile(wasm_bytes),
{:ok, inst_ref} <- QuickBEAM.Native.wasm_start(mod_ref, stack_size, heap_size) do
{:ok, %__MODULE__{module_ref: mod_ref, instance_ref: inst_ref}}
else
{:error, reason} -> {:stop, reason}
end
end
@impl true
def handle_call({:call, func_name, params}, _from, state) do
{:reply, QuickBEAM.Native.wasm_call(state.instance_ref, func_name, params), state}
end
def handle_call(:memory_size, _from, state) do
{:reply, QuickBEAM.Native.wasm_memory_size(state.instance_ref), state}
end
def handle_call({:memory_grow, delta}, _from, state) do
{:reply, QuickBEAM.Native.wasm_memory_grow(state.instance_ref, delta), state}
end
def handle_call({:read_memory, offset, length}, _from, state) do
{:reply, QuickBEAM.Native.wasm_read_memory(state.instance_ref, offset, length), state}
end
def handle_call({:write_memory, offset, data}, _from, state) do
{:reply, QuickBEAM.Native.wasm_write_memory(state.instance_ref, offset, data), state}
end
@impl true
def terminate(_reason, state) do
if state.instance_ref, do: QuickBEAM.Native.wasm_stop(state.instance_ref)
:ok
end
end