# `Vastlint`
[🔗](https://github.com/aleksUIX/vastlint-erlang/blob/main/lib/vastlint.ex#L1)

High-performance VAST XML validator for Elixir and Erlang.

Validates IAB VAST 2.0–4.3 tags against 191 rules covering required
elements, schema structure, security, deprecated features, and CTV
advisories. Backed by `vastlint-core` (Rust) via a DirtyCpu NIF -
validation never blocks BEAM schedulers regardless of tag size.

## Quick start

    iex> {:ok, result} = Vastlint.validate(xml)
    iex> result.valid
    true
    iex> result.summary.errors
    0

## With options

    iex> opts = [
    ...>   wrapper_depth: 2,
    ...>   max_wrapper_depth: 5,
    ...>   rule_overrides: %{"VAST-2.0-mediafile-https" => "off"}
    ...> ]
    iex> {:ok, result} = Vastlint.validate(xml, opts)

## Raising variant

    iex> result = Vastlint.validate!(xml)
    iex> Enum.filter(result.issues, &(&1.severity == :error))
    []

## Performance

At production VAST tag sizes (17–44 KB), validation completes in
363–2,104 µs per tag. The NIF runs on dirty CPU schedulers - concurrent
calls from many BEAM processes scale linearly with available cores.

See `vastlint.org` for full benchmark data.

# `validate`

```elixir
@spec validate(
  binary(),
  keyword()
) :: {:ok, Vastlint.Result.t()} | {:error, term()}
```

Validate a VAST XML binary or string using default settings.

Returns `{:ok, %Vastlint.Result{}}` on success, `{:error, reason}` on
bad input (empty binary, non-UTF-8 bytes).

A result with `valid: false` is still `{:ok, result}` - the error tuple
is reserved for call-level failures, not validation failures. Use
`result.valid` or `result.summary.errors` to check validation outcome.

## Example

    iex> {:ok, result} = Vastlint.validate(xml)
    iex> result.valid
    true

# `validate!`

```elixir
@spec validate!(
  binary(),
  keyword()
) :: Vastlint.Result.t()
```

Validate a VAST XML binary or string, raising on failure.

Returns `%Vastlint.Result{}` directly. Raises `Vastlint.ValidationError`
if the NIF call itself fails (not if the VAST tag is invalid - a tag with
errors still returns a Result with `valid: false`).

## Example

    iex> result = Vastlint.validate!(xml)
    iex> result.valid
    true

# `validate_batch`

```elixir
@spec validate_batch([binary()]) :: [ok: Vastlint.Result.t(), error: term()]
```

Validate a list of VAST XML binaries in a single NIF dispatch.

Uses Rayon (Rust's data-parallelism library) to validate all items
concurrently within one dirty-CPU scheduler call, eliminating the
per-call BEAM↔NIF round-trip overhead that limits throughput when
dispatching N individual `validate/1` calls from N BEAM processes.

Returns a list of `{:ok, %Vastlint.Result{}}` or `{:error, reason}`
tuples, one per input, in the same order as the input list.

## When to use

Use `validate_batch/1` when you have a burst of tags to validate
concurrently (e.g. an ad-server processing a pod of creatives, or a
pipeline validating a batch upload).  For single-tag validation,
`validate/1` is simpler.

## Example

    iex> results = Vastlint.validate_batch([xml1, xml2, xml3])
    iex> Enum.all?(results, fn {:ok, r} -> r.valid end)
    true

# `version`

```elixir
@spec version() :: binary()
```

Return the vastlint-core library version string, e.g. `"0.2.6"`.

---

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