hl7-parser
The most-used and most actively developed alternative. Parses structure without validating; optional Serde, and timestamps into chrono, time, or jiff; message building; cursor-by-character-index. Apache-2.0.
Comparison
Interface engines, the mature libraries on other platforms, the other Rust crates, and the pipe-splitting you were about to write yourself. When each is the right answer, and when this is the wrong one.
No performance comparison is claimed here. Nothing in this family has been benchmarked against another library. Comparing fairly means matching what each one actually does, and a parser that only splits on pipes is not doing the same work as one that preserves escape sequences and round-trips byte for byte. So this page compares capability and shape, which is checkable, rather than speed, which would not be. Our own measured figures, with their method, are on the benchmarks page.
Most comparisons in this space go wrong by putting products from three different categories into one table. The honest first question is what you are building.
| If you need to… | You want | This family |
|---|---|---|
| Run interfaces: routes, retries, queues, monitoring, on-call | An interface engine | Not that. Useful alongside one. |
| Write an application that happens to speak HL7® v2 | A library | Yes — er7, er7-redact, serde-er7 |
| Do a one-off transformation at a shell prompt | A command-line tool | Yes — two binaries, no Rust knowledge required |
| Validate a message against the standard’s tables | A conformance tool | No. Deliberately out of scope. |
| Speak the HL7® FHIR® standard | An HL7® FHIR® library | No. Different standard entirely. |
Open Integration Engine — the community fork of Mirth Connect, made after Mirth moved to a commercial-only license — and its commercial siblings are a different category of thing entirely. An engine gives you channels, routing, a management UI, transformers, persistence, retry, alerting, and an operations story. It is a system you deploy and run.
A library gives you a function call. If your problem is “forty interfaces, three hospitals, and someone has to be paged when one stops”, an engine is the right answer and no amount of crate substitutes for it.
These crates are useful alongside an engine rather than instead of it:
er7-redact --report prints the paths and
actions with no values in the output, which is the shape a ticket can
carry.HAPI HL7v2 is the reference open-source HL7 v2 library, in Java, dual licensed under MPL 1.1 and GPL 2.0. It has been maintained for two decades, ships a generated typed model for every segment and message of every release, and has seen far more real traffic than anything here. NHapi is its .NET port; hl7apy is the best-established Python option.
If your platform is the JVM, use HAPI. That is not modesty: a twenty-year-old library with complete release coverage and a large user base is the lower-risk choice, and reimplementing it in a language you were not otherwise using is a bad trade.
| The mature libraries | Here | |
|---|---|---|
| Typed model | Complete generated model: every segment, every release | None. A structural tree; meaning comes from the path |
| Validation | Conformance checking against the standard’s tables | None, on purpose |
| Runtime | A JVM, a CLR, or a Python interpreter | A static binary: no runtime, no GC |
| Dependency tree | Substantial, and audited as such | Zero, one, and two crates respectively |
| Round trip | Varies by parser and options | Byte for byte, as a tested guarantee |
| Track record | Two decades of production traffic | First published 2026-08-15. New. |
| License | MPL 1.1 or GPL 2.0, for HAPI | Five, at your option |
The license row decides some evaluations outright. A permissive option matters if you are linking into a closed-source product; a copyleft option matters if your organisation prefers one. Offering five is how this project avoids having that conversation with anyone.
A small field, and cooperation beats competition in it. The figures below were read from the crates.io API on 2026-08-26, as context rather than as a ranking.
hl7-parserThe most-used and most actively developed alternative. Parses structure without validating; optional Serde, and timestamps into chrono, time, or jiff; message building; cursor-by-character-index. Apache-2.0.
hl7v2-parserNewer. Zero-allocation where possible; a companion hl7v2_stream gives event-based streaming with bounded memory.
rust-hl7Buffer-copy-free indexing with HL7® notation; self-described as experimental; explicitly no plan for conformance checking. Last published 2021.
hl7-mllp-codecNot a parser at all: a Tokio codec for MLLP framing. Complementary to any of these, including er7.
These are real reasons, not hedges.
hl7-parser parses HL7 timestamps into chrono, time, or jiff. er7 returns the
text and leaves the interpretation to you, because doing otherwise means a dependency.hl7v2_stream is built for that; er7 parses a message into a tree.hl7-parser has a feature
flag. Here it is a separate crate, precisely so that users who do not want Serde do not pay
for it.er7, enforced by a test. The
dependency table is empty and a test fails if that changes. Criterion lives in a separate
unpublished workspace member so that even the development dependencies stay empty.er7-redact has no equivalent in the list above.The honest comparison, because it is what most teams actually do and it is sometimes right.
fields = line.split("|") # this works, until it doesn't When hand-rolling is right: you read one field, from one sender, whose messages you control, in a script that will not outlive the week.
When it stops being right, in roughly the order teams discover it:
\F\ is a literal | in a value.
Splitting on | cuts a value in half, silently.MSH segment is special. MSH-1 is the
field separator, so the segment does not index like any other.MSH-2 and you are expected to read them, not assume them.PID-13 may be one phone number or four, and
the code that assumed one is now wrong.The pitch is not “your split is wrong”. It is that the seven items above are
exactly what er7 implements, in about the same runtime cost, with a test for each
and no dependency to audit.
Stated here so no comparison implies otherwise.
Each crate’s own specification states its scope and its non-goals precisely; that is the
authoritative version of this list. The full write-up, with the reasoning, is COMPARISONS.md in the
repository.