Schema Language
Complete reference for the ZAP schema language
Schema Language
The ZAP schema language defines the structure of your messages. Schemas are compiled to generate type-safe code for your target language.
File Structure
Every schema file must start with a unique 64-bit ID:
The ID ensures that different schemas with the same type names do not conflict.
Primitive Types
| Type | Description | C++ Type | Size |
|---|---|---|---|
Void | No data | zap::Void | 0 bits |
Bool | Boolean | bool | 1 bit |
Int8 | Signed 8-bit | int8_t | 8 bits |
Int16 | Signed 16-bit | int16_t | 16 bits |
Int32 | Signed 32-bit | int32_t | 32 bits |
Int64 | Signed 64-bit | int64_t | 64 bits |
UInt8 | Unsigned 8-bit | uint8_t | 8 bits |
UInt16 | Unsigned 16-bit | uint16_t | 16 bits |
UInt32 | Unsigned 32-bit | uint32_t | 32 bits |
UInt64 | Unsigned 64-bit | uint64_t | 64 bits |
Float32 | 32-bit float | float | 32 bits |
Float64 | 64-bit float | double | 64 bits |
Text | UTF-8 string | zap::Text | pointer |
Data | Byte array | zap::Data | pointer |
Structs
Structs are the primary composite type:
Field Numbers
Each field has a number (@0, @1, etc.) that identifies it in the binary format. These numbers:
- Must be unique within a struct
- Must start at 0 and be sequential (no gaps in new schemas)
- Cannot be reused even after a field is removed
- Determine wire format order, not source order
Default Values
Fields can have default values:
Default values are encoded as XOR with the actual value, so defaults of zero take no space.
Enums
Enumerations define a set of named values:
Enum values also have ordinal numbers that cannot be reused.
Lists
Lists hold zero or more elements of a single type:
Unions
Unions allow a field to hold one of several types:
Anonymous Unions
Named Unions
Union with Void
Use Void for union members that carry no data:
Groups
Groups organize fields without adding pointer indirection:
Groups are purely organizational - they are stored inline in the parent struct.
Interfaces (RPC)
Interfaces define RPC methods:
Returning Capabilities
Methods can return interface references (capabilities):
Streaming
Use -> stream for methods that return multiple responses:
Generics
Schemas support generic (parameterized) types:
Imports
Schemas can import types from other files:
Import Paths
Annotations
Annotations attach metadata to schema elements:
Annotation Targets
Annotations can target:
file- The schema file itselfstruct- Struct definitionsfield- Struct fieldsunion- Union definitionsgroup- Group definitionsenum- Enum definitionsenumerant- Enum valuesinterface- Interface definitionsmethod- Interface methodsparam- Method parametersannotation- Other annotationsconst- Constants*- Any target
Constants
Define compile-time constants:
Schema Evolution
Safe Changes (Backward Compatible)
- Adding new fields (with new, higher ordinal numbers)
- Renaming fields or types (names are not in the wire format)
- Adding new enum values at the end
- Adding new union members
- Adding new methods to interfaces
- Changing a field from non-optional to optional
Breaking Changes (Avoid)
- Removing fields (mark as deprecated instead)
- Changing field types
- Reusing field numbers
- Changing field numbers
- Removing enum values
- Reordering enum values
- Changing method signatures
Deprecation Pattern
Best Practices
- Use meaningful field numbers - Group related fields with consecutive numbers
- Reserve field numbers - Leave gaps for future additions in related groups
- Document with annotations - Add
$docannotations for complex fields - Use enums for fixed sets - Better than strings for known values
- Prefer structs over unions - Unless data is truly mutually exclusive
- Keep interfaces focused - Small interfaces are easier to implement and mock
Next Steps
- Learn about Wire Format and Encoding
- Explore the RPC System
- See Examples