# `F3.IO.Memory`

In-memory byte source.

The struct keeps the caller's binary until `close/1`, which drops this
source's reference. `Inspect` does not print the bytes.

# `t`

```elixir
@type t() :: %F3.IO.Memory{closed: boolean(), data: binary(), size: non_neg_integer()}
```

In-memory source.

`data` is the caller's binary until close, then `<<>>`. `size` is the
length at open and does not change. `closed` is true after `close/1`.

# `close`

Drops this source's binary. A second close returns the same closed handle.

## Examples

    iex> {:ok, state} = F3.IO.Memory.open(<<1>>)
    iex> {:ok, closed} = F3.IO.Memory.close(state)
    iex> closed.closed
    true
    iex> {:error, error} = F3.IO.Memory.size(closed)
    iex> error.category
    :closed

# `open`

```elixir
@spec open(binary()) :: {:ok, t()} | {:error, F3.Error.t()}
```

Wraps `data`. The binary may be empty. Any other term is
`:invalid_argument` and does not raise.

## Examples

    iex> {:ok, state} = F3.IO.Memory.open(<<1, 2, 3, 4>>)
    iex> state.size
    4

    iex> {:error, error} = F3.IO.Memory.open(:nope)
    iex> error.category
    :invalid_argument

# `pread`

Reads at most `length` bytes at `offset`.

A start at or past the end is `{:ok, ""}`. A negative offset or length
is `:invalid_argument`. A closed handle is `:closed`.

## Examples

    iex> {:ok, state} = F3.IO.Memory.open(<<1, 2, 3, 4>>)
    iex> F3.IO.Memory.pread(state, 1, 2)
    {:ok, <<2, 3>>}
    iex> F3.IO.Memory.pread(state, 4, 2)
    {:ok, <<>>}

# `size`

Byte length stored at open. A closed handle is `:closed`.

## Examples

    iex> {:ok, state} = F3.IO.Memory.open("abcd")
    iex> F3.IO.Memory.size(state)
    {:ok, 4}

---

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