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 two releases, pinned once in the workspace root and inherited by every member. At the time of writing that is 1.96. Raising the floor is routine and expected, not a breaking change to be avoided. 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.

sh
# The umbrella crate: hl7::v2 and hl7::v3
cargo add hl7

# With the v2 derive macros
cargo add hl7 --features derive

Take a standard directly if you specifically want it without the indirection:

sh
# 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 derive

Or write the manifest yourself:

Cargo.toml

toml
[dependencies]
hl7 = { version = "0.2", features = ["derive"] }

# Or, taking v2 directly:
hl7-2 = { version = "0.3", 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.

CrateFeatureDefaultEffect
hl7deriveoffForwards to `hl7-2`’s `derive` feature.
hl7-2deriveoffAdds `#[derive(FromHl7)]` and `#[derive(ToHl7)]`; pulls in `hl7-2-derive`.
hl7-3deriveoffAdds `#[derive(FromElement)]`; pulls in `hl7-3-derive`.
hl7-2-mllpackonAcknowledgement generation; pulls in `hl7-2`.
hl7-2-mllpclockoff`acknowledge_now`; pulls in `chrono`. Implies `ack`.
hl7-2-mllpnoncomplianceoffThe 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

sh
# 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 clock

As 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.

sh
# 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-dictionary

Note 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

CrateLatestInstallWhat for
hl70.2.0cargo add hl7The umbrella crate: one module per HL7 standard
hl7-20.3.0cargo add hl7-2HL7 v2 itself: parse, navigate, validate, modify, render
hl7-30.2.0cargo add hl7-3HL7 v3: the RIM backbone, the data types, the message envelope
hl7-2-mllp0.2.0cargo add hl7-2-mllpMLLP: HL7 v2 framed on a TCP stream
hl7-2-soap0.2.0cargo add hl7-2-soapHL7 v2 carried in a SOAP envelope over HTTP
hl7-3-soap0.2.0cargo add hl7-3-soapHL7 v3 carried in a SOAP envelope over HTTP
hl7-2-from-er7-into-xml0.7.0cargo add hl7-2-from-er7-into-xmlER7 → the official v2.xml XML representation
hl7-2-from-xml-into-er70.7.0cargo add hl7-2-from-xml-into-er7v2.xml XML → ER7
hl7-2-from-er7-into-json0.5.0cargo add hl7-2-from-er7-into-jsonER7 → typed JSON
hl7-2-from-json-into-er70.5.0cargo add hl7-2-from-json-into-er7Typed JSON → ER7
hl7-2-derive0.2.0cargo add hl7-2-derive#[derive(FromHl7)] and #[derive(ToHl7)] for struct mode
hl7-3-derive0.2.0cargo add hl7-3-derive#[derive(FromElement)] for HL7 v3 struct mode
hl7-2-from-xsd-into-json-dictionary0.2.0cargo add hl7-2-from-xsd-into-json-dictionaryHL7 v2.xml XSDs → the JSON dictionary hl7-2 reads
hl7-2-xml-lite-helper0.2.0cargo add hl7-2-xml-lite-helperThe 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

sh
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.96 check --workspace --all-targets

One 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:

rust
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:

sh
$ printf 'MSH|^~\\&|LAB||EPIC||20260814080000||ORU^R01|1|P|2.5\rPID|1||241900\r' \
    | hl7-v2 --query PID-3
241900

If either works, go to the quick start. If neither does, the troubleshooting page covers the failures people actually hit.