# `Dicom.P10.Stream.Source`
[🔗](https://github.com/Balneario-de-Cofrentes/dicom/blob/v0.9.1/lib/dicom/p10/stream/source.ex#L1)

Data source abstraction for the streaming DICOM parser.

Provides a uniform interface over binary buffers and file I/O with
read-ahead buffering. The source supports three operations:

- `ensure/2` -- guarantee N bytes are available in the buffer
- `consume/2` -- consume N bytes from the buffer
- `peek/2` -- read N bytes without consuming

## Source Types

- **Binary**: wraps an in-memory binary, no I/O
- **File**: reads from a file handle with configurable read-ahead buffering

## Stability

This module **may change**. It is an internal implementation detail of the
streaming parser and should not be relied on directly by consumers.

# `io_device`

```elixir
@type io_device() :: pid() | {:file_descriptor, atom(), term()}
```

# `t`

```elixir
@type t() :: %Dicom.P10.Stream.Source{
  buffer: binary(),
  io: :eof | io_device() | nil,
  offset: non_neg_integer(),
  read_ahead: pos_integer()
}
```

# `available`

```elixir
@spec available(t()) :: non_neg_integer()
```

Returns the number of bytes currently available in the buffer.

# `bytes_consumed`

```elixir
@spec bytes_consumed(t()) :: non_neg_integer()
```

Returns the total bytes consumed from this source.

# `consume`

```elixir
@spec consume(t(), non_neg_integer()) :: {:ok, binary(), t()}
```

Consumes `n` bytes from the buffer, returning them and the updated source.

# `consume_until`

```elixir
@spec consume_until(t(), binary()) :: {:ok, binary(), t()}
```

Consumes bytes until `marker` is found, excluding the marker from the returned data.

If the marker is not found before EOF, consumes and returns the remaining buffer.

# `consume_until_required`

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

Consumes bytes until `marker` is found, excluding the marker from the returned data.

Returns `{:error, :unexpected_end}` if EOF is reached before the marker appears.

# `ensure`

```elixir
@spec ensure(t(), non_neg_integer()) :: {:ok, t()} | {:error, :unexpected_end}
```

Ensures at least `n` bytes are available in the buffer.

Returns `{:ok, source}` if the buffer has >= n bytes after filling,
or `{:error, :unexpected_end}` if the source is exhausted.

# `eof?`

```elixir
@spec eof?(t()) :: boolean()
```

Returns true if the source is exhausted (EOF and empty buffer).

# `from_binary`

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

Creates a source from an in-memory binary.

# `from_io`

```elixir
@spec from_io(
  io_device(),
  keyword()
) :: t()
```

Creates a source from an open file handle (opened in `:raw, :binary, :read` mode).

## Options

- `:read_ahead` -- preferred read-ahead buffer size in bytes (default: 65536)

# `peek`

```elixir
@spec peek(t(), non_neg_integer()) :: {:ok, binary()} | {:error, :unexpected_end}
```

Peeks at the next `n` bytes without consuming them.

---

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