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.

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

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