Expand description
European e-invoicing formats, on top of the EN 16931 semantic model.
┌──────────────┐ ┌──────────────────────┐
│ billing │ │ inbound documents │
│ calculations │ │ UBL / CII / EDIFACT │
└──────┬───────┘ └──────────┬───────────┘
│ adapter (optional feature) │
└──────────────┬───────────────────────────┘
▼
┌─────────────────────┐
│ en16931 │ semantic model, 316 rules,
│ proof of validity │ no XML, no PDF, no I/O
└──────────┬──────────┘
▼
┌─────────────────────┐
│ en16931-formats │ ← you are here
│ UBL · CII · PDF │
└─────────────────────┘en16931 decides whether an invoice is correct. This crate decides
what it looks like on the wire, and re-implements not one of the 316
rules.
§Why one crate, not one per format
XRechnung is carried in UBL and CII; every ZUGFeRD payload is CII. A crate
per format would need the CII binding twice, and two bindings drift. Cargo
features already express which syntax a consumer wants, so a crate boundary
here would be solving with a package what --no-default-features solves for
free.
What is a separate crate is en16931, and that boundary is
load-bearing: this crate depends on it, so rustc forbids the reverse. “The
semantic rules do not depend on a syntax” is enforced rather than asked for,
and en16931’s dependency graph stays at ten crates and builds for
wasm32.
§Features, and what each one costs
| Feature | Default | Graph | What |
|---|---|---|---|
ubl | ✅ | 13 crates | UBL 2.1, both directions |
cii | — | 13 crates | UN/CEFACT CII D16B, both directions |
zugferd | — | 57 crates | ZUGFeRD / Factur-X hybrid PDFs |
render | — | + a typesetting engine | Corporate design — not yet implemented |
zugferd is off by default and that matters: lopdf brings AES, ChaCha20,
SHA-2, getrandom and libc, and the result does not build for
wasm32-unknown-unknown. Nobody reading a UBL invoice should pay for that.
§The 91 % that costs a writer nothing
CEN’s artefacts carry 1 339 syntax rules, and 1 220 of them (91 %) say some element “shall not be used” — they fence off the parts of UBL 2.1 and CII D16B that EN 16931 does not use. That inverts the usual expectation:
- A writer driven from the semantic model cannot violate them. It has no
way to express
cbc:UUID, because the model has no term for it. They are unreachable, not cheaply satisfied — the same shape asInvoiceAmountmakingBR-DEC-*unrepresentable. So the writer answers to roughly 119 real rules. - A reader must cope with all 1 339, because the document came from somewhere else.
Unreachability is a claim, so the serialiser enforces it against the
prohibitions extracted from CEN’s own Schematron, and tests/subset.rs
asserts the writer never needs that safety net. See ubl::prohibitions.
§Quick start
use en16931::Invoice;
let xml = en16931_formats::ubl::to_string(&Invoice::default());
let read = en16931_formats::ubl::from_str(&xml).expect("readable");
assert!(read.unmapped.is_empty(), "nothing was silently dropped");§Attribution
The bindings are derived from CEN’s EUPL-1.2 validation artefacts and the element order from the authorities’ published instances. The notice is a licence condition, not decoration, and it has a test.
Re-exports§
Modules§
- cii
cii - The UN/CEFACT Cross Industry Invoice D16B binding, both directions.
- ubl
ubl - The UBL 2.1 binding, both directions.
- xrechnung
- XRechnung — which specification a document claims, and writing one that claims it.
- zugferd
zugferd - ZUGFeRD and Factur-X — invoices that are a PDF and machine-readable data.
Structs§
- NotValid
- A document was not written, because it did not pass the profile it was asked to be written for.
Enums§
- Syntax
- Which syntax a document is written in.
Constants§
- ATTRIBUTION
- The CEN attribution notice, as
en16931carries it.
Functions§
- sniff
- Guess the syntax from the document element, without parsing.