# `VFS.StreamOptions`
[🔗](https://github.com/ivarvong/vfs/blob/v0.1.0/lib/vfs/stream_options.ex#L1)

Helper module for backend authors implementing `stream_read/3`. Applies
the documented options (`:chunk_size`, `:byte_range`, `:line_range`) to
a binary content and returns a chunk Stream — or `{:error, :einval}`
for malformed options.

Every backend whose `stream_read/3` returns bytes (memory-backed,
postgres-backed, S3-backed, blob-store-backed) wants the same option
handling. Centralizing it here means:

  * No backend silently ignores documented options.
  * Validation is uniform — `:einval` triggers identical conditions
    across every backend, which the conformance suite enforces.
  * Bug fixes propagate to every backend (e.g. the `:line_range`
    `last < first` validation).

Usage from a `defimpl VFS.Mountable` block:

    def stream_read(%MyBackend{} = b, path, opts) do
      case fetch_content(b, path) do
        {:ok, content} ->
          case VFS.StreamOptions.apply(content, opts) do
            {:ok, stream} -> {:ok, stream, b}
            {:error, kind} -> {:error, VFS.Error.new(kind, path: path)}
          end

        :error ->
          {:error, VFS.Error.new(:enoent, path: path)}
      end
    end

# `apply`

```elixir
@spec apply(
  binary(),
  keyword()
) :: {:ok, Enumerable.t(binary())} | {:error, :einval}
```

Apply `:chunk_size`, `:byte_range`, and `:line_range` options to
`content`, returning `{:ok, chunk_stream}` or `{:error, :einval}`.

Order of operations: byte slice → line slice → chunk. So
`byte_range: {0, 100}, line_range: {1, 5}` means "first 100 bytes,
then take the first 5 lines of those." Mixing both is unusual but
the order is documented for predictability.

---

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