nir-rs
Pure-Rust implementation of the Neuromorphic Intermediate Representation (NIR)
Typed NIR graphs in Rust, with opt-in HDF5 .nir read/write that interoperates
with the official Python reference. The graph model has no system
dependencies; only the hdf5 feature links native libhdf5.
NIR is to spiking neural networks what ONNX is to conventional nets (or GGUF to LLMs): a framework-agnostic graph format so models can move between simulators and hardware without being rewritten.
Why nir-rs?
- Official NIR is primarily Python (neuromorphs/NIR)
- This crate is a pure-Rust graph model with the same wire types and HDF5 layout
- Suitable for embedded, server, and tooling pipelines that should not embed a Python runtime
- Opt-in HDF5 I/O and Serde for debug serialization — enable only what you need
Upstream
- Spec / reference: github.com/neuromorphs/NIR
- Primitives docs: neuroir.org
- Paper: Nature Communications (2024) (DOI 10.1038/s41467-024-52259-9) — cite
Wire compatibility: HDF5 node type strings must match the Python IR
(CubaLIF, Conv2d, SumPool2d, …), not informal aliases
(CurrLIF, Convolution, …).
Scope
This crate provides:
- The NIR graph model and standard node types
- Reading and writing
.nir(HDF5) files - Round-trip fidelity checks and structural validation
- An idiomatic Rust API (
NirGraph, closedNirNodeenum, tensors, errors)
This crate does not provide:
- SNN training or simulation
- Mapping graphs onto specific neuromorphic hardware
- Framework-specific importers/exporters (those belong in the tools that produce or consume NIR)
Status
| Version | Focus |
|---|---|
| 0.4.x (current) | Graph model, HDF5 I/O, Serde/debug DX, Docker image, crates.io |
| Earlier | Dual license, typed nodes, fixtures, CI hardening |
Release notes and the upstream compatibility matrix:
| Doc | Purpose |
|---|---|
| CHANGELOG.md | Keep a Changelog notes + 0.x versioning policy |
| COMPATIBILITY.md | Release ↔ upstream NIR, fidelity rules, features, MSRV |
Compatibility claims are fixture-backed (tests/fixtures/).
Install
[]
= "0.4.2"
HDF5 .nir I/O (needs a system libhdf5, or a static build — see File I/O):
[]
= { = "0.4.2", = ["hdf5"] }
Debug Serde (JSON / RON / etc.; not a wire standard):
[]
= { = "0.4.2", = ["serde"] }
From git — pin a release tag (same tree as the matching crates.io release once the tag exists):
= { = "https://github.com/Limen-Neural/nir-rs", = "v0.4.2" }
For unreleased work on the default branch:
= { = "https://github.com/Limen-Neural/nir-rs", = "main" }
Quick start
use ;
use ;
File I/O
.nir is the official NIR interchange format: an HDF5 container whose layout is
fixed by upstream. Files written here load in Python nir.read, and files
written by nir.write load here.
I/O is behind the opt-in hdf5 feature, which links native libhdf5.
Without that feature the crate has no system dependencies:
| Platform | System dependency |
|---|---|
| Debian / Ubuntu | apt install libhdf5-dev |
| Fedora | dnf install hdf5-devel |
| macOS | brew install hdf5 |
| Anywhere | depend on hdf5-metno = { version = "0.14", features = ["static", "zlib"] } — Cargo feature unification applies it to this crate's copy. A dependency cannot enable hdf5/static via this crate's feature list alone; without zlib the vendored build has no gzip filter. |
Without the feature, io::read / io::write still exist and return
NirError::Unimplemented, so downstream code compiles either way.
Round-trip fidelity is graph-level, not byte-level: node names and types,
ordered edges, and parameter values are preserved; HDF5 group order and chunk
layout may differ from h5py. In-memory dtypes (f32, f64, i64, bool)
round-trip exactly; narrower on-disk integers widen to i64 on read. Absent
optional fields (v_reset, w_in) use the same defaults as Python so graphs
match nir.read in memory.
Example: load, inspect, save a LIF graph
# optional paths:
Default input is tests/fixtures/lif_norse.nir; default output is a
PID-qualified file in the system temp directory.
Docker
Images ship a Rust 1.97 + libhdf5 environment with the crate sources and the
load_inspect_lif example binary (not an SNN simulator).
The same tags may also appear on Docker Hub; prefer GHCR for a stable, documented image path.
Local image:
Debug serialization
The opt-in serde feature implements Serialize / Deserialize for the graph
model. It is independent of hdf5:
[]
= { = "0.4.2", = ["serde"] }
= "1"
JSON is debug/test output, not a NIR interchange standard. Use HDF5 .nir
for Python and hardware tooling. JSON cannot represent NaN/infinities faithfully.
Toolchain
Rust 1.97.1 — rust-toolchain.toml, package.rust-version, and CI
(Linux / macOS / Windows) all pin the same version.
Develop
Wire compatibility is checked against real Python-written .nir fixtures under
tests/fixtures/ (BSD-3; see that directory's README). No Python interpreter is
required for default builds, tests, or CI.
API and fidelity details: COMPATIBILITY.md, docs.rs/nir-rs.
Citing NIR
If you use NIR in your work (including via this crate), please cite the Nature Communications paper:
Machine-readable form: CITATION.cff (GitHub “Cite this repository”).
Acknowledgements
NIR was originally conceived at the Telluride Neuromorphic Workshop 2023 by the authors below (alphabetical order), as listed by upstream neuromorphs/NIR:
- Steven Abreu
- Felix Bauer
- Jason Eshraghian
- Matthias Jobst
- Gregor Lenz
- Jens Egholm Pedersen
- Sadique Sheik
- Peng Zhou
This crate is an independent pure-Rust implementation of that IR; it is not the official Python reference package.
License
Dual-licensed under either:
- Apache License, Version 2.0 (LICENSE-APACHE-2.0 or https://www.apache.org/licenses/LICENSE-2.0)
- MIT License (LICENSE-MIT or https://opensource.org/licenses/MIT)
at your option.