hl7-rust

HL7 Rust

Rust libraries and command-line tools for HL7 version 2.5: a parser, dictionary, and validator at the core; MLLP and SOAP transports; and converters that move messages losslessly, in both directions, between the traditional pipe-delimited ER7 encoding and XML or JSON.

Core

The standards themselves, and the umbrella crate that re-exports them.

hl7-3

HL7 v3 for Rust: the Reference Information Model (RIM) backbone classes, coded values, and the three-level message envelope (transport wrapper, control act wrapper, domain payload). A foundation, not a full implementation.

hl7

The umbrella crate: re-exports one module per HL7 standard — hl7::v2 and hl7::v3 today, with room for hl7::fhir as that standard gets implemented.

Transports

hl7-2-mllp

HL7 v2 MLLP: the Minimal Lower Layer Protocol that frames HL7 version 2 messages on a TCP stream. Framing, streaming, acknowledgements, and a transport trait.

hl7-2-soap

HL7 v2 over SOAP: the envelope, faults, payload carriage, WSDL, and response evaluation that carry HL7 version 2 messages over HTTP instead of MLLP.

hl7-3-soap

HL7 v3 over SOAP: the envelope, faults, message carriage, WSDL, and the real HL7 v3 acknowledgement (MCCI_IN000002UV01) — SOAP is v3's own historically dominant transport, not an alternative to something else.

Format conversions

hl7-2-from-xml-into-er7

v2.xml XML back to ER7 — reads what the crate above writes, with no HL7 v2.5 dictionary of its own.

hl7-2-from-er7-into-json

ER7 to a typed JSON representation designed to preserve everything v2.xml preserves, using idiomatic JSON instead of XML's constructs.

hl7-2-from-json-into-er7

Typed JSON back to ER7 — reads what the crate above writes, with no HL7 v2.5 dictionary of its own.

All four crates share the same ER7 parser (er7 on crates.io). The two forward crates share the same HL7 v2.5 data-type tables and message-structure grammars — only the rendered output format differs. The two reverse crates need none of that: each element or key name a forward crate writes already carries its own position, so reversal is purely structural — see each reverse crate's spec/index.md §1.1.

Tooling

hl7-2-derive

Derive macros for the hl7-2 crate: #[derive(FromHl7)] and #[derive(ToHl7)] map struct fields to HL7 v2 message paths. Used through hl7-2's derive feature, not directly.

hl7-3-derive

Derive macro for the hl7-3 crate: #[derive(FromElement)] maps struct fields to HL7 v3 XML element attributes and children. Used through hl7-3's derive feature, not directly.

hl7-2-from-xsd-into-json-dictionary

Reads a directory of HL7 v2 XML Schema Definition (XSD) files — the v2.xml encoding, as published or as a vendor customised it — and writes the JSON dictionary the hl7-2 crate reads.

hl7-2-xml-lite-helper

A small, dependency-free XML reader shared by the hl7-2 crates: elements, attributes, text, and nesting, for documents whose shape you already know, with namespace prefixes ignored rather than resolved.

Example

An ER7 fragment such as:

PID|1||241900||TEST^FOUAZ

converts to XML

<PID>
  <PID.1>1</PID.1>
  <PID.3><CX.1>241900</CX.1></PID.3>
  <PID.5><XPN.1><FN.1>TEST</FN.1></XPN.1><XPN.2>FOUAZ</XPN.2></PID.5>
</PID>

and to JSON

{
  "PID": {
    "PID.1": "1",
    "PID.3": { "CX.1": "241900" },
    "PID.5": { "XPN.1": { "FN.1": "TEST" }, "XPN.2": "FOUAZ" }
  }
}

Piping either back through its reverse crate reproduces the original PID|1||241900||TEST^FOUAZ exactly — that round trip is a runnable example in each forward crate's own README.

What they do

  • ER7 parsing at every level: segments, fields, repetitions (~), components (^), and subcomponents (&).
  • Dynamic delimiters, read from MSH-1/MSH-2 rather than hardcoded.
  • Typed names: built-in HL7 v2.5 tables map each field of the common segments and composite types to its data type — Z-segments and uncommon types still convert, using positional generic names.
  • Message-structure groups for ACK, ADT_A01, ORM_O01, and ORU_R01, flattened back out again on the way in.
  • Graceful fallback rather than failure: unknown structures render flat, unknown fields use positional generic names.
  • The two reverse crates carry no HL7 v2.5 dictionary of their own — they reconstruct a message purely from the position each forward crate already encodes in every element/key name, and re-escape decoded text back to raw ER7.
  • None of the four crates is a validator — no schema, cardinality, or table checking is performed.

See Specs for where each project's normative conversion rules live.