Code generated from a schema
A schema compiler reads a message definition, such as a .proto file, and generates the types, encoder and decoder for your language.
How they work
Here you own the format. You define messages and fields, and the compiler decides the bytes. Protocol Buffers writes each field as a tag holding its field number and wire type, followed by the value: a varint, a fixed-size number, or a length and that many bytes. That is tag-length-value, so an old decoder skips fields added after it was built.
nanopb is a schema compiler for microcontrollers. It reads a standard .proto file and emits C structs plus field descriptors for a runtime of 5 to 20 kB of code that uses about 1 kB of stack. Options such as max_count and max_size turn repeated fields and strings into fixed arrays inside the struct, so decoding needs no malloc, and input that would overflow an array is rejected.
A schema can’t describe a format that already exists, because the compiler chooses the bytes; the Kaitai Struct FAQ says the two kinds of tool solve completely different problems. Schemaless binary formats such as CBOR sit in between: any decoder can read the data without a schema, and the CDDL notation can describe the expected shape when you want one.
Technologies
What all binary parsing and encoding have in common → nanopb | Open source | Open-source project by Petteri Aimonen | zlib | 2026-10-09 |
Sources
- Protocol Buffers docs: Encoding (tags, wire types, varints, TLV)
- nanopb docs: Overview (features and limitations)
- nanopb docs: Basic concepts (max_count, max_size, generated structs)
- Kaitai Struct FAQ: compared with Protocol Buffers, ASN.1, Thrift and others
- RFC 8949: Concise Binary Object Representation (CBOR)
- RFC 8610: Concise Data Definition Language (CDDL)
