npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

rust_iso20022

v0.1.1

Published

ISO 20022 message definitions and external code sets for Rust, generated from the official XSD schemas.

Readme

rust_iso20022

A Rust library for ISO 20022 (MX / SWIFT) financial messages, generated from the official iso20022.org XSD schemas. It provides a strongly-typed model for MX messages with XML and JSON parsing/serialization, message identification, a generic message tree for reading any message without the model, and business metadata extraction.

Installation

Add it with cargo (enable only the features you need — see Features):

cargo add rust_iso20022                                  # core: identify, MxNode, catalogue
cargo add rust_iso20022 --features model-pacs            # + the typed pacs model
cargo add rust_iso20022 --features model-pacs,serde,convert

or in Cargo.toml:

[dependencies]
# Core only (identification, generic tree, catalogue) — no model compiled.
rust_iso20022 = "0.1"

# Or pull in one or more typed message families plus JSON and typed scalars:
rust_iso20022 = { version = "0.1", features = ["model-pacs", "serde", "convert"] }

Enabling the umbrella model feature compiles all ~1130 message modules and is slow; prefer the per-area model-<area> features for the families you actually use.

Minimal first program — no features required:

use rust_iso20022::{detect, MxNode};

fn main() {
    let xml = r#"<Document xmlns="urn:iso:std:iso:20022:tech:xsd:pacs.008.001.08">
      <FIToFICstmrCdtTrf><GrpHdr><MsgId>ABC-1</MsgId></GrpHdr></FIToFICstmrCdtTrf>
    </Document>"#;

    let id = detect(xml).expect("recognised");
    println!("type = {}", id.message_name());            // pacs.008.001.08

    let doc = MxNode::parse(xml).unwrap();
    println!("MsgId = {:?}", doc.find("MsgId").and_then(|n| n.text())); // Some("ABC-1")
}

What's in the crate

| Layer | Module | Always available? | |-------|--------|-------------------| | Core | (root) | yes — MxId, BusinessArea, from_xml/to_xml, detect, MxNode, Error | | Catalogue | catalogue | yes — every message id + namespace as static phf tables | | Model | generated | per area — generated::<area>::<msg>::Document, enable with model-<area> |

Coverage: a typed model is generated for 1130 message versions across 32 business areas (acmt, admi, auth, caaa, caad, caam, cafc, cafm, cafr, cain, camt, canm, casp, casr, catm, catp, colr, fxtr, head, pacs, pain, reda, remt, secl, seev, semt, sese, setr, tsin, tsmt, tsrv, trck). This is the current iso20022.org catalogue (latest versions) plus the earlier versions, so older in-circulation messages still parse.

The generated types derive yaserde for XML and (with the serde feature) serde::{Serialize, Deserialize} for JSON.

Capabilities

| Capability | API | |---|---| | Typed model, all message versions | generated::<area>::<msg>::Document | | XML parse / serialize | from_xml / to_xml | | JSON parse / serialize (ISO element names) | from_json / to_json (feature serde) | | Per-message identity (namespace, MxId, area, functionality, variant, version) | the MxMessage trait on every Document | | Auto-detect & parse | detect, parse_as::<T>(), generated::any::parse_autoAnyMessage | | Business Application Header — read & build | app_hdr::parse_business_header / BusinessHeader::to_app_hdr_xml | | Business metadata extraction | metadata::extract | | Business message (header + typed document) | Envelope<D> / parse_envelope, read_business_message | | Generic tree — read any message without the model | MxNode::parse | | Typed scalars (amount → Decimal, dates → chrono) | convert::{to_decimal, to_date, to_datetime} (feature convert) | | Message catalogue | catalogue | | WebAssembly / JS bindings | src/wasm.rs (build via scripts/build-wasm.sh; see docs/wasm-api.md) |

Quick start

Identify a message and read its metadata — no model feature needed:

use rust_iso20022::{detect, BusinessArea, MxNode};

let xml = r#"<Document xmlns="urn:iso:std:iso:20022:tech:xsd:pacs.008.001.08">
  <FIToFICstmrCdtTrf><GrpHdr><MsgId>ABC-1</MsgId></GrpHdr>
    <CdtTrfTxInf><IntrBkSttlmAmt Ccy="EUR">1234.56</IntrBkSttlmAmt></CdtTrfTxInf>
  </FIToFICstmrCdtTrf></Document>"#;

let id = detect(xml).unwrap();
assert_eq!(id.message_name(), "pacs.008.001.08");
assert_eq!(id.business_area, BusinessArea::pacs);

// Read fields from the generic tree without the typed model:
let doc = MxNode::parse(xml).unwrap();
assert_eq!(doc.find("MsgId").and_then(|n| n.text()), Some("ABC-1"));
let amt = doc.find("IntrBkSttlmAmt").unwrap();
assert_eq!((amt.text(), amt.attr("Ccy")), (Some("1234.56"), Some("EUR")));

Typed parse / serialize (enable the area's model, e.g. cargo add rust_iso20022 -F model-pacs):

use rust_iso20022::generated::pacs::pacs_008_001_08::Document;

let doc: Document = rust_iso20022::from_xml(&xml)?;
let back: String = rust_iso20022::to_xml(&doc)?;

See the runnable examples:

cargo run --example inspect_message                                   # no features
cargo run --example typed_payment --features model-pacs,serde,convert # typed

Features

| Feature | Default | Effect | |---------|---------|--------| | model-<area> | no | the typed model for one business area, e.g. model-pacs. Enable only what you need — a single area compiles in seconds vs many minutes for all | | model | no | all model-<area> at once (~1130 modules; slow to compile) | | serde | no | serde + JSON (to_json/from_json) for the core, catalogue and message types | | convert | no | typed scalar conversions (to_decimal/to_date/to_datetime) via rust_decimal/chrono | | cli | no | the iso20022 command-line catalogue lookup tool | | catalogue | no | runtime XSD fetcher (fetch module): pulls in tokio, reqwest, regex |

The core (MxId, BusinessArea, MxNode, detect) and the catalogue are always available. The XSD → Rust generator is a separate, unpublished workspace crate (tools/codegen), so the published crate has no git dependencies.

Command-line tool

cargo run --features cli --bin iso20022 -- pacs.008   # all pacs.008 versions
# or after `cargo install rust_iso20022 --features cli`:
iso20022 camt          # every message in the camt business area
iso20022               # the whole catalogue

Regenerating the model

The model and catalogue are produced from the XSD schemas in xsds/ by the codegen tool:

cargo run -p rust_iso20022_codegen -- --input xsds --output src/generated

To (re)download schemas, the catalogue feature provides a Fetcher. The authoritative source is iso20022.org; its static schema path (/sites/default/files/documents/messages/<area>/schemas/<name>.xsd) is the reliable programmatic download path (Fetcher::download_schema).

Design notes

  • Scalars are String — lossless (exact text, no float rounding, ideal for money) and keeps XML and JSON in sync. Convert on demand with the convert feature.
  • Choices are modelled as a struct of Option<…> fields (the same shape JAXB uses), so an amount inside a <xsd:choice> round-trips with its Ccy attribute and unset choices are simply omitted.
  • JSON uses the ISO 20022 element names (MsgId, IBAN, …); to_json / from_json round-trip.
  • A value that is not a known member of a coded enumeration parses to an __Unknown__(String) fallback (surfaces only for invalid input).
  • XML round-tripping preserves the data model, not byte-for-byte formatting.

License

Apache-2.0.