Structs
Structs are a short naming for structures and define a series of data elements with their respective type. Those individual elements can be named or unnamed.
In schema they are declared with the struct
keyword followed by the name and the types contained.
The name must start with an uppercase ASCII character (A-Z
), and may be followed by zero or more upper- and lowercase ASCII characters and digits (A-Z
, a-z
, 0-9
).
Note that acronyms should be written in strict CamelCase, meaning Html
instead of HTML
or Api
instead of API
.
Individual fields in both named and unnamed form are separated by a comma ,
, and it's recommended to even give the last field a trailing comma. This allows for simpler diffs in version control systems.
Named
The likely most common form is a named struct. Named means that each element is represented as a field with a name to identify it.
To declare the struct as named the content is contained in curly braces {...}
.
A single field is defined as name: type @id
, the name, its type and ID. Field names must start with a lowercase ASCII character (a-z
) and may be followed by zero or more lowercase ASCII characters, digits and underscores (a-z
, 0-9
, _
).
Schema
Here is a basic named schema with two fields field1
and field2
. The first one is a 32-bit unsigned integer and assigned the ID 1. The second one is a 16-bit unsigned integer and assigned the ID 2.
struct Sample {
field1: u32 @1,
field2: u16 @2,
}
2
3
4
Languages
These samples describe how the schema would be defined in each language, when generating the code for it.
struct Sample {
pub field1: u32,
pub field2: u16,
// N fields...
}
2
3
4
5
type Sample struct {
Field1 uint32
Field2 uint16
// N fields...
}
func NewSample(field1 uint32, field2 uint16) Sample {
return Sample{
Field1: field1,
Field2: field2,
}
}
2
3
4
5
6
7
8
9
10
11
12
data class Sample(
val field1: UInt,
val field2: UShort,
// N fields...
)
2
3
4
5
class Sample {
field1: number;
field2: number;
// N fields...
constructor(field1: number, field2: number) {
this.field1 = field1;
this.field2 = field2;
}
}
2
3
4
5
6
7
8
9
10
@dataclass
class Sample:
field1: int
field2: int
2
3
4
Rust
Go
As Go allows to create new instances without declaring a value for each field (they default to the zero value), an additional constructor is created.
Kotlin
TypeScript
An additional constructor is required, to ensure all fields are properly initialized when creating new instances.
Python
In Python the @dataclass
attribute is used to define the fields of a class.
Unnamed
This variant is very similar to named structs, but in contrast lack a field name. They can be convenient if the data type is rather compact and explicit field names aren't needed. For example a position with the horizontal and vertical offset.
To declare the struct as unnamed the content is contained in parenthesis (...)
.
A single field is defined as type @id
, the name and ID.
Schema
struct Sample(u32 @1, u16 @2)
Languages
These samples describe how the schema would be defined in each language, when generating the code for it.
struct Sample(u32, u16);
type Sample struct {
F1 uint32
F2 uint16
}
func NewSample(f1 uint32, f2 uint16) Sample {
return Sample{
F1: f1,
F2: f2,
}
}
2
3
4
5
6
7
8
9
10
11
data class Sample(
val f1: UInt,
val f2: UShort,
)
2
3
4
class Sample {
fields: [number, number];
constructor(fields: [number, number]) {
this.fields = fields;
}
}
2
3
4
5
6
7
@dataclass
class Sample(tuple[int, int]):
pass
2
3
Unit
In addition to the above, a struct can completely omit field definitions. That is call a unit struct and doesn't carry any data. It doesn't take any space in encoded form either.
For most languages, this type doesn't take up any memory either. Creating some vector or list of said type would require zero bytes.
Instead, it's only the type that carries information.
Schema
struct Sample
Languages
These samples describe how the schema would be defined in each language, when generating the code for it.
struct Sample;
type Sample struct{}
class Sample
class Sample {}
@dataclass
class Sample:
pass
2
3
Generics
Schema
struct Pair<K, V> {
key: K @1,
value: V @2,
}
2
3
4
Languages
These samples describe how the schema would be defined in each language, when generating the code for it.
struct Pair<K, V> {
pub key: K,
pub value: V,
}
2
3
4
type Pair[K any, V any] struct {
Key K
Value V
}
2
3
4
data class Pair<K, V>(
val key: K,
val value: V,
)
2
3
4
class Pair<K, V> {
key: K;
value: V;
constructor(key: K, value: V) {
this.key = key;
this.value = value;
}
}
2
3
4
5
6
7
8
9
K = TypeVar("K")
V = TypeVar("V")
@dataclass
class Pair(Generic[K, V]):
key: K
value: V
2
3
4
5
6
7
8