Every value carries its width, base, and physical unit inline — no schema, just
human-readable text. A bare 9.81 is never ambiguous, and a mismatched
unit is a parse error.
You saw the syntax — here's a spacecraft running on it. One format, the whole loop:
config in, telemetry out. Edit the orbit; the craft encodes each measurement into a
.bvnr frame and the ground station decodes it — the orbit you see is drawn only from those
decoded values, a full round-trip through the format. Units, bit-widths and types ride
inside the stream; no schema required. Hover a gauge to jump to the line it decoded.
.bvnr document you can edit freely. Nothing changes until you press Apply..bvnr, the same format you just edited — units and types travel right alongside the numbers.
This is the reference C reader's on_verified callback stream, reproduced in the browser —
the same events, in the same order, that bvnr_read() delivers. Bare values get the
validator's synthesised default annotation; type, range, base and unit violations surface on the
separate on_error channel, exactly as the C core reports them.
In science and industry the costly failures are rarely bad syntax — they are unit confusion:
pounds-force read as newtons, feet as meters. The number parses fine; the
9.81 is right but the context is
wrong. Bovnar keeps that context — width, base, and unit — inline with every value, as
plain human-readable text with no external schema, and rejects a mismatched unit as a parse
error rather than a silent bug.
uint:16 stays exactly 16 bits: it can’t silently widen to 64, nor be reinterpreted as a float.11001010 is never mistaken for a decimal. Values whose digits include letters (e.g. hex ff) are written as a quoted string: <uint:_16> "ff".s⁻²) or a plain-ASCII caret (s^-2) interchangeably.s⁻², m²) and an all-ASCII form that uses a caret for the
exponent and * in place of the · separator. k~g*m*s^-2 and
k~g·m·s⁻² parse to exactly the same unit. The ASCII form needs no obscure glyphs, so it’s the
natural choice for hand-authoring .bvnr. The writer emits Unicode superscripts by default, or
the caret form when you set BVN_UNIT_ASCII_EXP.
All of it is optional: omit annotations for well-defined defaults (uint:64,
float:64), or add them for full parser validation. Both modes are unambiguous —
and a .bvnr file stays UTF-8 prose you can read in any editor, no toolchain required.
Every assignment is a declaration: the annotation is part of the value, not a note about it.
on_unverified / on_verified callback pair.
No heap required for the lexer itself.
NumPy bridge that loads typed arrays
straight into an ndarray with the physical unit attached.
bvnr_read_flags_t. Both callbacks receive the event type and parsed data.loads / dumps interface. Pure-ctypes — no compiled extension required.loads(typed=True) wraps each typed value in a Quantity that preserves its exact text, bit width, and unit. Pass the dict directly back to dumps() for a lossless round-trip.numpy.ndarray — bovnar widths map to native dtypes (float:32 → float32) and the whole-array unit rides alongside. NumPy is an optional, lazily-imported extra (pip install "bovnar[numpy]").libm is the only mandatory dependency.Reach for Bovnar when units must travel with the data and the receiver may not share a schema. Every measurement is unit-safe by construction — a mismatched unit is a parse error, not a silent bug discovered in production.
Readings stay self-describing from the lab bench to the published dataset — width, base, and physical unit ride along with every value.
Pressures, flows, and temperatures cross process boundaries without a shared contract, and dimensional mismatches are caught at the parse step.
Heterogeneous devices emit human-readable, type-precise records that any consumer can validate on its own, no central registry required.
Data written today still means exactly the same thing decades from now — the meaning lives in the file, not in lost tooling.
Ten documents — from a five-minute tutorial to the formal EBNF grammar and conformance protocol. Read inline below, or download the full set as PDF.
loads/dumps and streaming Reader/Writer.Print-ready, self-contained PDFs of every document — or grab the complete set as one archive.
↓ Download all