# `Bourse.Parser`
[🔗](https://github.com/ZenHive/bourse/blob/main/lib/bourse/parser.ex#L1)

Public response parser facade.

# `apply_mappings`

```elixir
@spec apply_mappings(term(), map(), keyword() | map()) ::
  {:ok, struct() | [struct()]} | {:error, term()}
```

Applies a v4 normalization mapping to raw response data.

# `parse`

```elixir
@spec parse(term(), map() | nil, module(), keyword()) ::
  {:ok, struct() | [struct()]} | {:error, term()}
```

Parses `data` against a single normalization-slot mapping into `target`.

This is the runtime entry point for the generated per-exchange `parse_*`
functions (`parse_ticker/2`, `parse_trade/2`, …). It applies the **Honesty
Rule** to the authored field maps before delegating to
`apply_mappings/3`:

  * `operation_supported: false` → `{:error, {:unsupported_operation, slot}}`
    (the venue does not offer this parse slot)
  * `nil` slot (upstream never derived a field map) → `{:error, :no_field_map}`
  * non-`nil` `_unresolved_reason` (upstream flagged the slot as not safely
    derivable) → `{:error, {:unresolved, reason}}` — the partial field map is
    **not** applied, so callers never receive a struct silently built from an
    incomplete mapping
  * resolved slot with a non-empty `field_map` or `branches` → parsed

`opts` may carry `:market` (a market-info map), `:symbol`, `:route` (the
selected endpoint path), `:currencies` (the loaded currency catalog), and
`:envelope` (the original decoded response); all are threaded into the parser
context.

## Examples

    iex> Bourse.Parser.parse(%{}, nil, Bourse.Ticker)
    {:error, :no_field_map}

    iex> Bourse.Parser.parse(%{}, %{"_unresolved_reason" => "identifier_return"}, Bourse.Market)
    {:error, {:unresolved, "identifier_return"}}

---

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