If this work helps you, please support it: Become a supporter
Write your data types once and generate code to read and write them in six languages.
package example
const MaxHealth = 1000
enum ShipType { Fighter, Corvette, Bomber }
flags ShipFlags { Firing, Thrusting, Disabled }
type Vec3
{
x float64
y float64
z float64
}
type Quaternion
{
x float64
y float64
z float64
w float64 = 1.0
}
type ShipState
{
ship_type ShipType
ship_flags ShipFlags
position Vec3
rotation Quaternion
health int32 | min = 0, max = MaxHealth
at_rest bool
if !at_rest
{
linear_velocity Vec3
angular_velocity Vec3
}
}
This declaration compiles to C, C++, C#, Go, Rust and JavaScript code that reads and writes your data types and agrees on every bit. Now your native plugin, your Unity client, your Go backend, your browser client, and your tooling all speak the same language.
Multiplayer games serialize the same data in several languages at once — an engine client here, a dedicated server there, tools and services around them. Every way of solving that costs something:
Generating the code takes the fourth path. One declaration produces the reader and the writer, in every language, so they cannot disagree — and because the format is decided at compile time, what comes out is the straight-line code you would have hand-written, not an interpreter walking a schema at runtime.
| min = 0, max = 1000 costs 10 bits, not
4 bytes. Bounds are part of the type, and the wire cost follows from them.if !at_rest { … } omits whole field groups
from the wire, back-referencing a bool already sent.| min, max, resolution sends a step index, not a
float. A 0–1 throttle at 0.01 costs 7 bits.fixed(48, 16) and its unsigned
sibling ufixed(48, 16) are declared like any other field, and the compiler
owns both the storage and the wire for them.go build -o /usr/local/bin/schema ./cmd/schema
schema check <dir of .schema files>
schema generate --lang c|cpp|cs|go|js|rust --out <outdir> <dir>
USAGE.md is the guide — every language feature, with real examples and the code each one generates, and how to drive the compiler from Go instead of the command line.
Building the tests needs the six serialize runtimes checked out beside this
repo, then make test — CONTRIBUTING.md has the clone
list and what the gates prove.
| Document | What's in it |
|---|---|
| USAGE.md | Every language feature, with the code it generates. Start here. |
| PERFORMANCE.md | Generated-code benchmarks, and how to read them honestly. |
| SPEC.md | The normative reference — grammar, wire law, every edge case. |
| COMPARISON.md | The same packet in schema, Cap'n Proto, Protobuf and FlatBuffers — 28 vs 52 vs 56 vs 72 bytes, measured, with a script to re-run it. |
| FAQ.md | Isn't this just FlatBuffers / Protobuf / Cap'n Proto? And other blunt questions. |
| VERSIONING.md | What a version number promises — chiefly that a 1.x upgrade will not move your wire. |
| CONTRIBUTING.md | How to build it, the gates a change has to pass, and what a golden change means. |
| SECURITY.md | The threat model, and how to report a vulnerability privately. |
The compiler is AGPL-3.0 — and will stay that way. The code it generates is yours.
Glenn Fiedler and Rowan Claude, Más Bandwidth LLC.
Hacker News (1)
Go
29.9%
JavaScript
27.2%
C#
10.9%
C
9.7%
C++
8.6%
Rust
8.3%
Shell
5.0%
If this work helps you, please support it: Become a supporter
Write your data types once and generate code to read and write them in six languages.
package example
const MaxHealth = 1000
enum ShipType { Fighter, Corvette, Bomber }
flags ShipFlags { Firing, Thrusting, Disabled }
type Vec3
{
x float64
y float64
z float64
}
type Quaternion
{
x float64
y float64
z float64
w float64 = 1.0
}
type ShipState
{
ship_type ShipType
ship_flags ShipFlags
position Vec3
rotation Quaternion
health int32 | min = 0, max = MaxHealth
at_rest bool
if !at_rest
{
linear_velocity Vec3
angular_velocity Vec3
}
}
This declaration compiles to C, C++, C#, Go, Rust and JavaScript code that reads and writes your data types and agrees on every bit. Now your native plugin, your Unity client, your Go backend, your browser client, and your tooling all speak the same language.
Multiplayer games serialize the same data in several languages at once — an engine client here, a dedicated server there, tools and services around them. Every way of solving that costs something:
Generating the code takes the fourth path. One declaration produces the reader and the writer, in every language, so they cannot disagree — and because the format is decided at compile time, what comes out is the straight-line code you would have hand-written, not an interpreter walking a schema at runtime.
| min = 0, max = 1000 costs 10 bits, not
4 bytes. Bounds are part of the type, and the wire cost follows from them.if !at_rest { … } omits whole field groups
from the wire, back-referencing a bool already sent.| min, max, resolution sends a step index, not a
float. A 0–1 throttle at 0.01 costs 7 bits.fixed(48, 16) and its unsigned
sibling ufixed(48, 16) are declared like any other field, and the compiler
owns both the storage and the wire for them.go build -o /usr/local/bin/schema ./cmd/schema
schema check <dir of .schema files>
schema generate --lang c|cpp|cs|go|js|rust --out <outdir> <dir>
USAGE.md is the guide — every language feature, with real examples and the code each one generates, and how to drive the compiler from Go instead of the command line.
Building the tests needs the six serialize runtimes checked out beside this
repo, then make test — CONTRIBUTING.md has the clone
list and what the gates prove.
| Document | What's in it |
|---|---|
| USAGE.md | Every language feature, with the code it generates. Start here. |
| PERFORMANCE.md | Generated-code benchmarks, and how to read them honestly. |
| SPEC.md | The normative reference — grammar, wire law, every edge case. |
| COMPARISON.md | The same packet in schema, Cap'n Proto, Protobuf and FlatBuffers — 28 vs 52 vs 56 vs 72 bytes, measured, with a script to re-run it. |
| FAQ.md | Isn't this just FlatBuffers / Protobuf / Cap'n Proto? And other blunt questions. |
| VERSIONING.md | What a version number promises — chiefly that a 1.x upgrade will not move your wire. |
| CONTRIBUTING.md | How to build it, the gates a change has to pass, and what a golden change means. |
| SECURITY.md | The threat model, and how to report a vulnerability privately. |
The compiler is AGPL-3.0 — and will stay that way. The code it generates is yours.
Glenn Fiedler and Rowan Claude, Más Bandwidth LLC.
Hacker News (1)
Go
29.9%
JavaScript
27.2%
C#
10.9%
C
9.7%
C++
8.6%
Rust
8.3%
Shell
5.0%