YAML, parsed at
library speed.
yeptris is the YAML counterpart of libleptris: a YAML 1.2 parser, writer and streamer in pure C11 — zero required dependencies, a stable C ABI, opaque handles — with a Psych-compatible Ruby gem and a PyYAML-compatible Python package shaped like the incumbents.
- Speed with a referee — every figure comes from the open benchmark lane: interleaved runs, pinned competitors, medians, a performance ledger kept in the repository.
- Conformance first — 395/395 on the yaml-test-suite, the libyaml emission goldens with zero divergences, ASan/UBSan/TSan suites, and a nightly libFuzzer lane.
- One core, three surfaces — the same C11 engine from C, Ruby, and Python; bindings version in lockstep with the engine.
What it is
An engine built like a ledger, not a claim
yeptris is YAML 1.2 first — with a libyaml/Psych-compatible YAML 1.1 lenient mode for the real world. The yaml-test-suite is the conformance bar; every divergence is documented; every performance statement reproduces from the benchmark harness and the ledger (benchmarks/PERF-LEDGER.md).
The race, in the open
Same-binary, min-of-N against libyaml: scalar-heavy 3.36×, block-nested ~2.3×, wide mappings ~2.4×, anchor-heavy ~1.8×. The interleaved head-to-head against rapidyaml runs in CI on every push — nine document shapes across DOM, pull, recorder and emit.
Conformant where it counts
The full verification matrix: yaml-test-suite pinned atda267a5, psych-pure’s 67 corpus files, JSONTestSuite 95/95 accept and 188/188 reject in strict mode, 405-input libyaml parse differential with full-record equality, 1091 fuzz inputs across chunkings.
Beyond the DOM
Three consumption models over one engine: pull events (StAX-style, zero C→host callbacks — the FFI-friendly form), libyaml-compatible push events, and a packed record tape for bulk drains. Plans and schemas walk documents into typed columns with no intermediate tree. Zero-copy value views in C.
Packaging that installs
Ruby: fat platform gems (no C extension — FFI), every major OS×arch tier, lockstep-released with the engine. Python: self-contained wheels over ctypes, zero compilation at install. C: cmake --install with pkg-config.
The surface
Shaped like the incumbents
Ruby mirrors Psych (its YAML 1.1 implicit typing is the default; schema: :core_12 switches to the 1.2 core schema), and drops in beside it — including the error names. Python mirrors PyYAML’s safe surface.
#include <yeptris/yeptris.h>
YeptrisStatus st;
YeptrisDocument doc = yeptris_parse(data, len, &st);
if (!doc) {
uint32_t line, col;
const char *msg = yeptris_last_error(&line, &col); /* 1-based */
}
size_t n = yeptris_document_count(doc);
YeptrisNode root = yeptris_document_root(doc, 0);
YeptrisNode port = yeptris_node_map_get(root, "port", 4);
char *out = NULL; size_t out_len = 0;
out = yeptris_serialize(doc, &out_len); /* canonical YAML */
yeptris_document_free(doc); /* one free for everything */The chase begins
Install, three ways
| surface | command | what you get |
|---|---|---|
| Ruby | gem install yeptris | a prebuilt platform gem where one exists — FFI over the shared library, zero compilation at install |
| Python | pip install yeptris | a self-contained wheel — ctypes FFI over libyeptris, PyYAML-compatible semantics |
| C | cmake -B build -S . && cmake --build build | LTO on by default; cmake --install carries headers and pkg-config |
Fast as hares.
Parsed at library speed.
yeptris v0.6.22 — libyeptris v0.6.22, the yeptris gem v0.6.22.1, the yeptris package v0.6.22.1. Repos canonical: yeptris, yeptris-ruby, yeptris-py.