Documentation
Install
Every crate, every feature flag, and the command-line tools. Most people need exactly one line of this page.
Requirements
A Rust toolchain, and nothing else. There is no C dependency, no build script that shells out, and no vendored binary anywhere in the workspace.
The minimum supported Rust version is current stable minus three releases,
pinned as rust-version in every member's Cargo.toml. At the time of
writing that is 1.95. Raising the floor is treated as a breaking change. See Versions and compatibility for the policy in full.
As a library
Most users want the umbrella crate. It is a thin re-export — hl7::v2 is the hl7-2 crate and hl7::v3 is hl7-3 — with room left for hl7::fhir. Nothing lives at its root, because a “message”, a “segment”, and a
“code” mean different things in each standard.
# The umbrella crate: hl7::v2 and hl7::v3
cargo add hl7
# With the v2 derive macros
cargo add hl7 --features deriveTake a standard directly if you specifically want it without the indirection:
# HL7 v2 only, no umbrella indirection
cargo add hl7-2
cargo add hl7-2 --features derive
# HL7 v3 only
cargo add hl7-3
cargo add hl7-3 --features deriveOr write the manifest yourself:
Cargo.toml
[dependencies]
hl7 = { version = "0.1", features = ["derive"] }
# Or, taking v2 directly:
hl7-2 = { version = "0.2", features = ["derive"] }Cargo features
Nothing in this workspace is on by default that costs you a dependency, with one exception — hl7-2-mllp's ack feature, which is on because an MLLP receiver that
cannot acknowledge is not much use.
| Crate | Feature | Default | Effect |
|---|---|---|---|
hl7 | derive | off | Forwards to `hl7-2`’s `derive` feature. |
hl7-2 | derive | off | Adds `#[derive(FromHl7)]` and `#[derive(ToHl7)]`; pulls in `hl7-2-derive`. |
hl7-3 | derive | off | Adds `#[derive(FromElement)]`; pulls in `hl7-3-derive`. |
hl7-2-mllp | ack | on | Acknowledgement generation; pulls in `hl7-2`. |
hl7-2-mllp | clock | off | `acknowledge_now`; pulls in `chrono`. Implies `ack`. |
hl7-2-mllp | noncompliance | off | The default framing tolerance becomes lenient. |
The derive macros live in their own crates precisely so that the default build of hl7-2 keeps exactly one dependency: syn and quote are
compiled only for callers who ask for the macros.
MLLP, whose feature set is the most interesting
# Everything: framing, streaming, transport, acknowledgement
cargo add hl7-2-mllp
# Framing, streaming, and transport with no dependencies at all
cargo add hl7-2-mllp --no-default-features
# Add acknowledge_now, which needs a clock
cargo add hl7-2-mllp --features clockAs a command-line tool
Six crates ship a binary. They are useful on their own — the first thing to do with a message from a vendor you have never seen is look at it, and that does not need a Rust project.
# The HL7 v2 tool. The binary is named hl7-v2.
cargo install hl7-2
# The four converters, each its own binary
cargo install hl7-2-from-er7-into-xml
cargo install hl7-2-from-xml-into-er7
cargo install hl7-2-from-er7-into-json
cargo install hl7-2-from-json-into-er7
# The dictionary builder
cargo install hl7-2-from-xsd-into-json-dictionaryNote the name: cargo install hl7-2 installs a binary called hl7-v2. The crate is published as hl7-2 because hl7-v2 on crates.io is an unrelated package; the binary kept the readable name.
Full flag reference: Command line.
Every crate, and its install line
| Crate | Latest | Install | What for |
|---|---|---|---|
hl7 | 0.1.1 | cargo add hl7 | The umbrella crate: one module per HL7 standard |
hl7-2 | 0.2.3 | cargo add hl7-2 | HL7 v2 itself: parse, navigate, validate, modify, render |
hl7-3 | 0.1.3 | cargo add hl7-3 | HL7 v3: the RIM backbone, the data types, the message envelope |
hl7-2-mllp | 0.1.3 | cargo add hl7-2-mllp | MLLP: HL7 v2 framed on a TCP stream |
hl7-2-soap | 0.1.1 | cargo add hl7-2-soap | HL7 v2 carried in a SOAP envelope over HTTP |
hl7-3-soap | 0.1.1 | cargo add hl7-3-soap | HL7 v3 carried in a SOAP envelope over HTTP |
hl7-2-from-er7-into-xml | 0.6.0 | cargo add hl7-2-from-er7-into-xml | ER7 → the official v2.xml XML representation |
hl7-2-from-xml-into-er7 | 0.6.0 | cargo add hl7-2-from-xml-into-er7 | v2.xml XML → ER7 |
hl7-2-from-er7-into-json | 0.4.2 | cargo add hl7-2-from-er7-into-json | ER7 → typed JSON |
hl7-2-from-json-into-er7 | 0.4.2 | cargo add hl7-2-from-json-into-er7 | Typed JSON → ER7 |
hl7-2-derive | 0.1.3 | cargo add hl7-2-derive | #[derive(FromHl7)] and #[derive(ToHl7)] for struct mode |
hl7-3-derive | 0.1.1 | cargo add hl7-3-derive | #[derive(FromElement)] for HL7 v3 struct mode |
hl7-2-from-xsd-into-json-dictionary | 0.1.1 | cargo add hl7-2-from-xsd-into-json-dictionary | HL7 v2.xml XSDs → the JSON dictionary hl7-2 reads |
hl7-2-xml-lite-helper | 0.1.1 | cargo add hl7-2-xml-lite-helper | The small, dependency-free XML reader this family shares |
Versions are the latest published at the time of writing, shown so you can tell roughly how
settled a crate is — not as a constraint to copy. Let cargo add pick.
One crate in the dependency map is not in this workspace: er7, the ER7 encoding layer, which is
its own repository and its own crate. You rarely add it directly — hl7-2 and the
conversion crates re-export what you need.
Building from source
git clone https://github.com/hl7-rust/hl7-rust
cd hl7-rust
cargo build # every workspace member
cargo test # every workspace member's tests
cargo build -p hl7-2 # just one
# Check against the minimum supported Rust version
cargo +1.95 check --workspace --all-targetsOne Cargo.lock at the workspace root covers every member; a crate does not carry
its own. Member crates depend on each other by relative path, exactly as they did when they
were sibling repositories — the flat one-directory-per-crate layout was kept specifically so
those paths did not have to change.
Verifying the install
The smallest thing that proves the library is wired up:
use hl7::v2;
fn main() -> Result<(), v2::Error> {
let text = "MSH|^~\\&|LAB||EPIC||20260814080000||ORU^R01|MSG00042|P|2.5\r\
PID|1||241900||EVERYWOMAN^EVE";
let message = v2::parse(text)?;
assert_eq!(message.structure_id(), "ORU_R01");
assert_eq!(message.get("PID-5.1")?.as_deref(), Some("EVERYWOMAN"));
println!("ok");
Ok(())
}And the same for the command-line tool:
$ printf 'MSH|^~\\&|LAB||EPIC||20260814080000||ORU^R01|1|P|2.5\rPID|1||241900\r' \
| hl7-v2 --query PID-3
241900If either works, go to the quick start. If neither does, the troubleshooting page covers the failures people actually hit.