# `Wasmex.Pipe`

A Pipe is a memory buffer that can be used in exchange for a Wasm file.

Pipes have a read and write position which can be set using `seek/2`.

## Example

Pipes can be written to and read from:

    iex> {:ok, pipe} = Wasmex.Pipe.new()
    iex> Wasmex.Pipe.write(pipe, "hello")
    {:ok, 5}
    iex> Wasmex.Pipe.seek(pipe, 0)
    iex> Wasmex.Pipe.read(pipe)
    "hello"

They can be used to capture stdout/stdin/stderr of WASI programs:

    iex> {:ok, stdin} = Wasmex.Pipe.new()
    iex> {:ok, stdout} = Wasmex.Pipe.new()
    iex> {:ok, stderr} = Wasmex.Pipe.new()
    iex> Wasmex.Store.new_wasi(%Wasmex.Wasi.WasiOptions{
    ...>   stdin: stdin,
    ...>   stdout: stdout,
    ...>   stderr: stderr,
    ...> })

# `t`

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

# `new`

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

Creates and returns a new Pipe.

## Example

    iex> {:ok, %Wasmex.Pipe{}} = Wasmex.Pipe.new()

# `read`

```elixir
@spec read(t()) :: binary()
```

Reads all available bytes from the Pipe and returns them as a binary.

This function does not block if there are no bytes available.
Reading starts at the current read position, see `seek/2`, and forwards the read position to the end of the Pipe.
The read bytes are not erased and can be read again after seeking back.

## Example

    iex> {:ok, pipe} = Wasmex.Pipe.new()
    iex> Wasmex.Pipe.write(pipe, "hello")
    iex> Wasmex.Pipe.read(pipe) # current position is at EOL, nothing more to read
    ""
    iex> Wasmex.Pipe.seek(pipe, 0)
    iex> Wasmex.Pipe.read(pipe)
    "hello"
    iex> Wasmex.Pipe.seek(pipe, 3)
    iex> Wasmex.Pipe.read(pipe)
    "lo"
    iex> Wasmex.Pipe.read(pipe)
    ""

# `seek`

```elixir
@spec seek(t(), integer()) :: :ok | :error
```

Sets the read/write position of the Pipe to the given position.

The position is given as a number of bytes from the start of the Pipe.

## Example

    iex> {:ok, pipe} = Wasmex.Pipe.new()
    iex> Wasmex.Pipe.write(pipe, "hello")
    iex> Wasmex.Pipe.seek(pipe, 0)
    :ok
    iex> Wasmex.Pipe.read(pipe)
    "hello"

# `size`

```elixir
@spec size(t()) :: integer()
```

Returns the current size of the Pipe in bytes.

## Example

    iex> {:ok, pipe} = Wasmex.Pipe.new()
    iex> Wasmex.Pipe.size(pipe)
    0
    iex> Wasmex.Pipe.write(pipe, "hello")
    iex> Wasmex.Pipe.size(pipe)
    5

# `write`

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

Writes the given binary into the pipe.

Writing starts at the current write position, see `seek/2`, and forwards it.

## Example

    iex> {:ok, pipe} = Wasmex.Pipe.new()
    iex> Wasmex.Pipe.write(pipe, "hello")
    {:ok, 5}
    iex> Wasmex.Pipe.seek(pipe, 0)
    iex> Wasmex.Pipe.read(pipe)
    "hello"

---

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