# `HL7v2`
[🔗](https://github.com/Balneario-de-Cofrentes/hl7v2/blob/v3.10.1/lib/hl7v2.ex#L1)

Pure Elixir HL7 v2.x toolkit.

Schema-driven parsing, typed segment structs, programmatic message
building, validation, and integrated MLLP transport.

## Parsing

    # Raw mode — canonical round-trip, delimiter-based
    {:ok, raw} = HL7v2.parse(text)

    # Typed mode — segments become structs
    {:ok, msg} = HL7v2.parse(text, mode: :typed)

## Building

    msg =
      HL7v2.new("ADT", "A01", sending_application: "PHAOS")
      |> HL7v2.Message.add_segment(%HL7v2.Segment.PID{...})

    text = HL7v2.encode(msg)

## Acknowledgments

    {:ok, typed} = HL7v2.parse(wire, mode: :typed)
    msh = hd(typed.segments)
    {ack_msh, msa} = HL7v2.ack(msh)

## MLLP Transport

    {:ok, _} = HL7v2.MLLP.Listener.start_link(port: 2575, handler: MyHandler)

# `ack`

```elixir
@spec ack(
  HL7v2.Segment.MSH.t(),
  keyword()
) :: {HL7v2.Segment.MSH.t(), HL7v2.Segment.MSA.t()}
```

Builds an ACK (Application Accept) for the given MSH segment.

Shortcut for `HL7v2.Ack.accept/2`.

## Options

  * `:text` — optional text message for MSA-3
  * `:message_control_id` — override the generated ACK message control ID

## Examples

    {ack_msh, msa} = HL7v2.ack(original_msh)

# `encode`

```elixir
@spec encode(HL7v2.RawMessage.t() | HL7v2.Message.t() | HL7v2.TypedMessage.t()) ::
  binary()
```

Encodes an HL7v2 message to wire format.

Accepts:

- `%HL7v2.RawMessage{}` — encodes directly
- `%HL7v2.Message{}` — converts to raw via `Message.encode/1`
- `%HL7v2.TypedMessage{}` — converts to raw via `TypedParser.to_raw/1`, then encodes

## Examples

    wire = HL7v2.encode(raw_message)
    wire = HL7v2.encode(builder_message)
    wire = HL7v2.encode(typed_message)

# `fetch`

```elixir
@spec fetch(HL7v2.TypedMessage.t(), binary() | HL7v2.Path.t()) ::
  {:ok, term()} | {:error, atom()}
```

Fetches a value, returning `{:ok, value}` or `{:error, reason}`.

# `get`

```elixir
@spec get(HL7v2.TypedMessage.t(), binary() | HL7v2.Path.t()) :: term()
```

Gets a value from a typed message using a path string like `"PID-5"` or a `%HL7v2.Path{}` struct.

# `get`

```elixir
@spec get(HL7v2.TypedMessage.t(), binary() | HL7v2.Path.t(), term()) :: term()
```

Gets a value from a typed message with a default.

# `new`

```elixir
@spec new(binary(), binary(), keyword()) :: HL7v2.Message.t()
```

Builds a new HL7v2 message. Shortcut for `HL7v2.Message.new/3`.

## Options

  * `:sending_application` — string or `%HD{}`
  * `:sending_facility` — string or `%HD{}`
  * `:receiving_application` — string or `%HD{}`
  * `:receiving_facility` — string or `%HD{}`
  * `:message_control_id` — string (default: auto-generated)
  * `:processing_id` — string (default: `"P"`)
  * `:version_id` — string (default: `"2.5.1"`)

## Examples

    msg = HL7v2.new("ADT", "A01", sending_application: "PHAOS")

# `parse`

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

Parses an HL7v2 message from a binary string.

## Options

- `:mode` — `:raw` (default) or `:typed`
- `:validate` — `true` to validate after parsing (default `false`).
  Requires `mode: :typed`; silently ignored in `:raw` mode.
- `:copy` — `true` to copy all parsed binaries (prevents GC reference to original
  message binary). Use when storing parsed messages long-term. Default `false`.

## Examples

    {:ok, msg} = HL7v2.parse("MSH|^~\\&|...")
    {:ok, msg} = HL7v2.parse(text, mode: :typed, validate: true)
    {:ok, msg} = HL7v2.parse(text, copy: true)

# `type`

```elixir
@spec type(HL7v2.RawMessage.t()) :: {:ok, HL7v2.TypedMessage.t()} | {:error, term()}
```

Converts a `%HL7v2.RawMessage{}` to a `%HL7v2.TypedMessage{}`.

Shortcut for `HL7v2.TypedParser.convert/1`.

## Examples

    {:ok, raw} = HL7v2.parse(wire)
    {:ok, typed} = HL7v2.type(raw)

# `validate`

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

Validates an HL7v2 typed message.

Returns `:ok` when all validation rules pass, or `{:error, errors}` with
a list of error/warning maps. Requires a `HL7v2.TypedMessage` -- raw messages
return `{:error, :not_a_typed_message}`.

Version-aware rules (v2.7+ B-field exemptions, etc.) are driven by MSH-12
(`version_id`) by default. Pass `:version` to override this — useful for
validating messages that mis-declare their version or when cross-checking
a v2.5.1 payload against v2.7 conformance rules.

## Options

- `:mode` -- `:lenient` (default) or `:strict`
- `:validate_tables` -- `true` to check coded fields against HL7 tables
  (default `false`)
- `:version` -- explicit HL7 version override (e.g. `"2.7"`). When provided,
  version-specific rules use this value instead of the one extracted from
  MSH-12. Invalid or unrecognized versions fall back to the MSH-12 value.
- `:profile` -- a `HL7v2.Profile` struct (or list of profiles) to validate
  against in addition to the base schema. Profiles express organization-
  specific constraints: required segments, required fields beyond the base
  spec, table bindings, cardinality, value predicates, and custom rules.
  Profile errors include a `:rule` (which rule type fired) and `:profile`
  (profile name) for traceability.

## Examples

    {:ok, msg} = HL7v2.parse(text, mode: :typed)
    :ok = HL7v2.validate(msg)

    # With table validation
    {:error, errors} = HL7v2.validate(msg, validate_tables: true)

    # Override the version read from MSH-12 and apply v2.7 rules instead
    :ok = HL7v2.validate(msg, version: "2.7")

    # Validate against a conformance profile
    profile =
      HL7v2.Profile.new("Hospital_ADT_A01", message_type: {"ADT", "A01"})
      |> HL7v2.Profile.require_field("PID", 18)
      |> HL7v2.Profile.require_cardinality("OBX", min: 1, max: 10)

    HL7v2.validate(msg, profile: profile)

---

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