# `Wasmex.Module`

A compiled WebAssembly module.

A Wasm Module contains stateless WebAssembly code that has
already been compiled and can be instantiated multiple times.

# `t`

```elixir
@type t() :: %Wasmex.Module{reference: reference(), resource: binary()}
```

# `compile`

```elixir
@spec compile(Wasmex.StoreOrCaller.t(), binary()) :: {:ok, t()} | {:error, binary()}
```

Compiles a Wasm module from it's Wasm (a .wasm file) or WAT (a .wat file) representation.

Compiled modules can be instantiated using `Wasmex.start_link/1` or `Instance.new/3`.

Since module compilation takes time and resources but instantiation is
comparatively cheap, it may be a good idea to compile a module once and
instantiate it often if you want to run a Wasm binary multiple times.

## Example

Read a Wasm file and compile it into a Wasm module.
Use the compiled module to start a running `Wasmex.Instance`.

    iex> {:ok, store} = Wasmex.Store.new()
    iex> {:ok, module} = Wasmex.Module.compile(store, File.read!(TestHelper.wasm_test_file_path()))
    iex> {:ok, _pid} = Wasmex.start_link(%{store: store, module: module})

Modules can be compiled from WAT (WebAssembly Text) format:

    iex> wat = "(module)" # minimal and not very useful
    iex> {:ok, store} = Wasmex.Store.new()
    iex> {:ok, %Wasmex.Module{}} = Wasmex.Module.compile(store, wat)

# `exports`

```elixir
@spec exports(t()) :: %{required(String.t()) =&gt; any()}
```

Lists all exports of a Wasm module.

Returns a map which has the exports name (string) as key and export info-tuples as values.
Info tuples always start with an atom indicating the exports type:

* `:fn` (function)
* `:global`
* `:table`
* `:memory`

Further parts of the info tuple vary depending on the type.

## Example

List the exported function "hello_world()" of a Wasm module:

    iex> {:ok, store} = Wasmex.Store.new()
    iex> wat = "(module
    ...>          (func $helloWorld (result i32) (i32.const 42))
    ...>          (export \"hello_world\" (func $helloWorld))
    ...>        )"
    iex> {:ok, module} = Wasmex.Module.compile(store, wat)
    iex> Wasmex.Module.exports(module)
    %{
      "hello_world" => {:fn, [], [:i32]},
    }

# `imports`

```elixir
@spec imports(t()) :: %{required(String.t()) =&gt; any()}
```

Lists all imports of a WebAssembly module grouped by their module namespace.

Returns a map of namespace names to namespaces with each namespace being a map again.
A namespace is a map of imports with the import name as key and and info-tuple as value.

Info tuples always start with an atom indicating the imports type:

* `:fn` (function)
* `:global`
* `:table`
* `:memory`

Further parts of the info tuple vary depending on the type.

## Example

Show that the Wasm module imports a function "inspect" from the "IO" namespace:

    iex> {:ok, store} = Wasmex.Store.new()
    iex> wat = "(module
    ...>          (import \"IO\" \"inspect\" (func $log (param i32)))
    ...>        )"
    iex> {:ok, module} = Wasmex.Module.compile(store, wat)
    iex> Wasmex.Module.imports(module)
    %{
      "IO" => %{
        "inspect" => {:fn, [:i32], []},
      }
    }

# `name`

```elixir
@spec name(t()) :: binary() | nil
```

Returns the name of the current module if a name is given.

This name is normally set in the Wasm bytecode by some compilers.

## Example

    iex> {:ok, store} = Wasmex.Store.new()
    iex> wat = "(module $hiFromTheDocs)" # minimal and not very useful Wasm module
    iex> {:ok, module} = Wasmex.Module.compile(store, wat)
    iex> Wasmex.Module.name(module)
    "hiFromTheDocs"

# `serialize`

```elixir
@spec serialize(t()) :: {:ok, binary()} | {:error, binary()}
```

Serializes a compiled Wasm module into a binary.

The generated binary can be deserialized back into a module using `unsafe_deserialize/1`.
It is unsafe do alter the binary in any way. See `unsafe_deserialize/1` for safety considerations.

## Example

Serializes a compiled module:

    iex> {:ok, store} = Wasmex.Store.new()
    iex> {:ok, module} = Wasmex.Module.compile(store, File.read!(TestHelper.wasm_test_file_path()))
    iex> {:ok, serialized} = Wasmex.Module.serialize(module)
    iex> is_binary(serialized)
    true

# `unsafe_deserialize`

```elixir
@spec unsafe_deserialize(binary(), Wasmex.Engine.t() | nil) ::
  {:ok, t()} | {:error, binary()}
```

Deserializes an in-memory compiled module previously created with
`Wasmex.Module.serialize/1` or `Wasmex.Engine.precompile_module/2`.

This function will deserialize the binary blobs emitted by
`Wasmex.Module.serialize/1` and `Wasmex.Engine.precompile_module/2`
back into an in-memory `Wasmex.Module` that's ready to be instantiated.

# Unsafety

This function is marked as `unsafe` because if fed invalid input or used
improperly this could lead to memory safety vulnerabilities. This method
should not, for example, be exposed to arbitrary user input.

The structure of the binary blob read here is only lightly validated
internally in `wasmtime`. This is intended to be an efficient
"rehydration" for a `Wasmex.Module` which has very few runtime checks
beyond deserialization. Arbitrary input could, for example, replace
valid compiled code with any other valid compiled code, meaning that
this can trivially be used to execute arbitrary code otherwise.

For these reasons this function is `unsafe`. This function is only
designed to receive the previous input from `Wasmex.Module.serialize/1`
and `Wasmex.Engine.precompile_module/2`. If the exact output of those
functions (unmodified) is passed to this function then calls to this
function can be considered safe. It is the caller's responsibility to
provide the guarantee that only previously-serialized bytes are being
passed in here.

Note that this function is designed to be safe receiving output from
*any* compiled version of `wasmtime` itself. This means that it is safe
to feed output from older versions of Wasmtime into this function, in
addition to newer versions of wasmtime (from the future!). These inputs
will deterministically and safely produce an error. This function only
successfully accepts inputs from the same version of `wasmtime`.
(this means that if you cache blobs across versions of wasmtime you can
be safely guaranteed that future versions of wasmtime will reject old
cache entries).

It is best to deserialize modules using an Engine with the same
configuration as the one used to serialize/precompile it.

## Example

Serializes a compiled module and deserializes it again:

    iex> {:ok, store} = Wasmex.Store.new()
    iex> {:ok, module} = Wasmex.Module.compile(store, File.read!(TestHelper.wasm_test_file_path()))
    iex> {:ok, serialized} = Wasmex.Module.serialize(module)
    iex> {:ok, %Wasmex.Module{}} = Wasmex.Module.unsafe_deserialize(serialized)

---

*Consult [api-reference.md](api-reference.md) for complete listing*
