Teptris — the TOML gem v0.2.47
A native C-extension binding (no FFI, no fallback) over libteptris v0.1.27. API shape and value semantics mirror the tomlib gem: offset and local datetimes become Time, dates become Date, local times stay String.
Installation
gem install teptrisRubyGems resolves a prebuilt platform gem where one exists: fat gems for x86_64/aarch64 Linux (glibc and musl), macOS (x86_64/arm64) and Windows (mingw and ucrt), each carrying one extension per Ruby minor (3.3–4.0); 32-bit ARM, big-endian s390x/ppc64le and the msvcrt-era Ruby 3.0 tier are emulated or pinned builds. Every other platform gets the source gem, which compiles the vendored engine with the installing Ruby’s own toolchain — a C compiler is required, and the install fails loudly without one.
Usage
require "teptris"
Teptris::TOML.load("title = \"teptris\"\n[owner]\nname = \"t\"\n")
# => {"title" => "teptris", "owner" => {"name" => "t"}}
Teptris::TOML.dump({"title" => "teptris", "owner" => {"name" => "t"}})
begin
Teptris::TOML.load("a = [1,")
rescue Teptris::ParseError => e
e.line # 1
e.column # 8
endBoth directions are native: dump walks the object tree in C through the builder API, so the engine emitter is the single formatting source (canonical output, 3–10× tomlib per shape). End to end, load is 7–110× tomlib and 20–280× toml-rb per shape.
The value contract
| TOML | Ruby |
|---|---|
| offset datetime | Time (fixed offset) |
| local datetime | Time |
| local date | Date |
| local time | String (the tomlib contract) |
| integer / float / string / bool / array / table | the obvious Ruby types |
Many documents — batch and lazy
# Eager: one Array of Hashes, same datetime contract as TOML.load
docs = Teptris::TOML.load_batch(toml_strings,
safe_load: [Time, Date],
datetime_policy: :native)
# File paths
docs = Teptris::TOML.load_files(["a.toml", "b.toml", "c.toml"])
# Lazy twin: parse N eagerly, materialize only along touched paths
arr = Teptris::TOML.load_lazy_batch(toml_strings)
arr.each { |doc | doc["x"].value }
# Threaded (0.2.52+): the C parse releases the GVL — parses overlap
# across Ruby threads; materialization serializes. Opt-in, 1 = default.
docs = Teptris::TOML.load_batch(toml_strings, threads: 4)Lazy loading
Teptris::TOML.load_lazy parses once and materializes host objects only along the paths actually touched — the complementary path when the schema is not known up front.
Schema descriptor plans
Compile a plan once, materialize only the planned keys in one native pass — Teptris::Descriptor /Teptris::TOML.load_schema (shipped since 0.2.29; the C ABI lives in libteptris teptris/plan.h). The walk returns a nested Hash with String keys and already-cast Ruby values:
DESC = Teptris::Descriptor.build(
children: [
{ name: "id", kind: :scalar },
{ name: "tags", kind: :collection }, # array of scalars
{ name: "items", kind: :nested, plan: { # table or [[aot]]
children: [{ name: "sku", kind: :scalar }] } },
{ name: "extra", kind: :raw }, # escape hatch: full subtree
])
Teptris::TOML.load_schema(toml_string, DESC)
# => {"id"=>1, "tags"=>["a","b"], "items"=>[{"sku"=>"x"}], "extra"=>{...}}
# unplanned keys never appearRow kinds: :scalar (any TOML value),:collection (array of scalars), :nested(recurse via plan:; spans arrays of tables),:raw (the untouched subtree). Absent planned keys read asnil.
Where to go next
- leptris/teptris-ruby — the canonical repository and its full platform matrix.
- The C engine under the gem
- The Python sibling package
This is the curated guide. The repositories are canonical: when this page and the repo disagree, the repo wins. Full documentation lives with the source.