# `Wasmex.Memory`

Memory is a linear array of bytes to store Wasm values. The `Memory` module provides functions to read and write to this array.

`Memory` is accessible through `Wasmex.Instance.memory/2`,
`Wasmex.Memory.from_instance/2`, or as the caller context
of an imported function (see `Wasmex.Instance.call_exported_function/5`).

    iex> %{store: store, module: module} = TestHelper.wasm_module()
    iex> {:ok, instance} = Wasmex.Instance.new(store, module, %{})
    iex> {:ok, memory} = Wasmex.Instance.memory(store, instance)
    iex> Wasmex.Memory.set_byte(store, memory, 0, 42)
    iex> Wasmex.Memory.get_byte(store, memory, 0)
    42

Wasm memory is organized in pages of 64kb and may be grown by additional pages.

# `t`

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

# `from_instance`

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

Returns the exported memory resource of the given `Wasmex.Instance`.

## Example

    iex> %{store: store, module: module} = TestHelper.wasm_module()
    iex> {:ok, instance} = Wasmex.Instance.new(store, module, %{})
    iex> {:ok, %Wasmex.Memory{}} = Wasmex.Memory.from_instance(store, instance)

# `get_byte`

```elixir
@spec get_byte(Wasmex.StoreOrCaller.t(), t(), non_neg_integer()) :: number()
```

Returns the byte at the given `index`.

## Example

Set a value at memory position `0` and read it back:

    iex> %{store: store, module: module} = TestHelper.wasm_module()
    iex> {:ok, instance} = Wasmex.Instance.new(store, module, %{})
    iex> {:ok, memory} = Wasmex.Memory.from_instance(store, instance)
    iex> Wasmex.Memory.set_byte(store, memory, 0, 42)
    iex> Wasmex.Memory.get_byte(store, memory, 0)
    42

# `grow`

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

Grows the amount of available memory by the given number of pages.

Returns the number of previously available pages.
A page has a size of 64 kB or 65,536 bytes.

Returns an error if memory could not be grown.

## Example

    iex> %{store: store, module: module} = TestHelper.wasm_module()
    iex> {:ok, instance} = Wasmex.Instance.new(store, module, %{})
    iex> {:ok, memory} = Wasmex.Memory.from_instance(store, instance)
    iex> Wasmex.Memory.grow(store, memory, 1)
    17

# `read_binary`

```elixir
@spec read_binary(
  Wasmex.StoreOrCaller.t(),
  t(),
  non_neg_integer(),
  non_neg_integer()
) :: binary()
```

Reads the given number of bytes from the given memory at the given index.

Returns the read bytes as a binary.

## Example

Reads 5 bytes from memory position `0`, given it contains the 5 ASCII
characters forming "hello".

    iex> %{store: store, module: module} = TestHelper.wasm_module()
    iex> {:ok, instance} = Wasmex.Instance.new(store, module, %{})
    iex> {:ok, memory} = Wasmex.Memory.from_instance(store, instance)
    iex> Wasmex.Memory.write_binary(store, memory, 0, "hello")
    iex> Wasmex.Memory.read_binary(store, memory, 0, 5)
    "hello"
    iex> Wasmex.Memory.read_binary(store, memory, 3, 2)
    "lo"

# `read_string`

```elixir
@spec read_string(
  Wasmex.StoreOrCaller.t(),
  t(),
  non_neg_integer(),
  non_neg_integer()
) :: String.t()
```

Reads the given number of bytes from the given memory at the given index.

Returns the read bytes as a string.

## Example

Reads 5 bytes from memory position `0`, given it contains the 5 ASCII
characters forming "hello".

    iex> %{store: store, module: module} = TestHelper.wasm_module()
    iex> {:ok, instance} = Wasmex.Instance.new(store, module, %{})
    iex> {:ok, memory} = Wasmex.Memory.from_instance(store, instance)
    iex> Wasmex.Memory.write_binary(store, memory, 0, "hello")
    iex> Wasmex.Memory.read_string(store, memory, 0, 5)
    "hello"
    iex> Wasmex.Memory.read_string(store, memory, 3, 2)
    "lo"

# `set_byte`

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

Sets the byte at the given `index` to the given `value`.

## Example

Set a value at memory position `0` and read it back:

    iex> %{store: store, module: module} = TestHelper.wasm_module()
    iex> {:ok, instance} = Wasmex.Instance.new(store, module, %{})
    iex> {:ok, memory} = Wasmex.Memory.from_instance(store, instance)
    iex> Wasmex.Memory.set_byte(store, memory, 0, 42)
    iex> Wasmex.Memory.get_byte(store, memory, 0)
    42

# `size`

```elixir
@spec size(Wasmex.StoreOrCaller.t(), t()) :: pos_integer()
```

Returns the size in bytes of the given memory.

Note that the size of the memory is always a multiple of 64kb (one page).

## Example

    iex> %{store: store, module: module} = TestHelper.wasm_module()
    iex> {:ok, instance} = Wasmex.Instance.new(store, module, %{})
    iex> {:ok, memory} = Wasmex.Memory.from_instance(store, instance)
    iex> Wasmex.Memory.size(store, memory)
    1114112 # in bytes (17 pages of 64 kB)

# `write_binary`

```elixir
@spec write_binary(
  Wasmex.StoreOrCaller.t(),
  t(),
  non_neg_integer(),
  binary()
) :: :ok
```

Writes the given `binary` into the memory at the given `index`.

## Example

Writes 5 bytes representing the ASCII characters for "hello"
at memory position `0`.

    iex> %{store: store, module: module} = TestHelper.wasm_module()
    iex> {:ok, instance} = Wasmex.Instance.new(store, module, %{})
    iex> {:ok, memory} = Wasmex.Memory.from_instance(store, instance)
    iex> Wasmex.Memory.write_binary(store, memory, 0, "hello")
    :ok

---

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