Skip to content

v2.5.0 — every protocol id moves; tables in nine languages; write checks are debug-only

Latest

Choose a tag to compare

@gafferongames gafferongames released this 07 Sep 19:49
· 411 commits to main since this release

What you get

  • Tables in all nine languages. C, C#, Go, Rust, Java, JavaScript, Dart and Elixir join C++: every language reads and writes fixed-class tables (with ?T optional fields and [E]T enum-keyed arrays) on the tolerant wire, the JSON text form and the reflection descriptors. Block and cook readers are in every language; the block builder is in C++ and C, and the cook's write side is in C++.
  • The tables language grew, in the C++ reference. Arrays of pointers and of unions, optional arrays, unbounded []T, map[K]V, *bytes and *string blobs, string/bytes/flags defaults, was on tables, enum variants and union arms, and a union arm that takes any field type. ROADMAP.md says what each other language carries today.
  • A leaner table wire, in C++. Files use the id-table form: each 64-bit name hash appears once, in a table at the end, so a file naming forty ids across ten thousand fields carries forty ids. A message form for tables over a connection, with batching and a bitpacked body. Unknown fields can be retained through a read, values widen on read, and every refusal has a name. The other eight languages write the previous form today and move to this one in a later release.
  • The cook and the block form. schema cook, cook-check and uncook are complete to the byte; C++ cooks from code as well as from the tool; every fixed table has a block form on the side at zero cost to the ordinary headers.
  • Packet wire, in all nine languages. wstring(N) wide strings. Malformed UTF-8 is refused on read in every build mode. string, bytes and flags fields take declared defaults. A union arm with no payload is encoded as its tag alone. Every enum exports Count beside Max.
  • Write-side checks are debug-only. In C, C++, C#, Rust, Java, Dart and JavaScript's flat tier, a release build no longer checks what you write; a debug build asserts it at the site. Go and Elixir keep refusing in every build, because those languages have no debug-only idiom, and JavaScript's stream tier still refuses in every build for now. Read-side checks run in every build, everywhere.
  • Faster in release. With the write-side checks compiled out, Rust's packet write is 11.6% faster and C#'s 9.2%, and C's read path closed to a statistical tie with C++. The README's table was measured on a new machine, so its percentages do not compare with 2.4.0's; PERFORMANCE.md says what moved.
  • Docs. TUTORIAL.md takes you from an empty directory to every feature. VERSIONING.md states the commitment for both wires. PORTING.md, COMPETITION.md, COMPARISON-TABLES.md and ROADMAP.md are new. Every page but README.md and ROADMAP.md now lives under docs/.
  • Tooling. Only schema fmt writes a schema file; every other command leaves your files alone. schema pack and schema unpack turn a directory tree into a table file and back. schema tables-baseline commits a projection that schema check diffs against, so an edit that changes what already-written data means cannot slip through unannounced.

Compatibility

Every protocol id moves. Rebuild and redeploy both peers together: a 2.4.0 peer refuses a 2.5.0 one rather than misreading it. Table files written under 2.4.0 do not open under 2.5.0; the table wire is pre-release until 3.0.0.

A schema stops compiling if a field's range excludes zero and it declares no default (an array cannot take a default, so widen its range), or if an enum has a variant named Count. [E.Max]T in a table body is refused; spell it [E]T. wstring(N) inside a table generates for C++ only.