222 lines
9.0 KiB
Markdown
222 lines
9.0 KiB
Markdown
# Syntax Documentation
|
|
|
|
bproto uses a custom syntax `bproto` (file extension `.bproto`).
|
|
Each protocol is described in a single bproto file.
|
|
|
|
For Beginners, a simple example of a protocol definition and usage can be found [here](/docs/quickstart.md).
|
|
|
|
The protocol definitions consist of the following basic components: **messages**, **enums**, **bitfields**, and the **protocol tag line**.
|
|
|
|
## Table of Contents
|
|
- [Syntax Documentation](#syntax-documentation)
|
|
- [Table of Contents](#table-of-contents)
|
|
- [Names and IDs](#names-and-ids)
|
|
- [Protocol Tag Line](#protocol-tag-line)
|
|
- [Message](#message)
|
|
- [Fields](#fields)
|
|
- [Datatypes](#datatypes)
|
|
- [Bitfields](#bitfields)
|
|
- [Enumerations](#enumerations)
|
|
- [Comments](#comments)
|
|
|
|
## Names and IDs
|
|
Names of enums, bitfields, messages, and fields support any letter (lower and uppercase), numbers, and underscores.
|
|
|
|
Regular expression: `[a-zA-Z0-9_]+`
|
|
|
|
Numbers/IDs are decimal encoded numbers. Trailing zeros are ignored.
|
|
|
|
Regular expression: `[0-9]+`
|
|
|
|
## Protocol Tag Line
|
|
This is a short description of the protocol consisting of a name and a version number.
|
|
This must be the first line of any bproto definition file.
|
|
|
|
**Syntax:**
|
|
```bproto
|
|
protocol <name> version <version>
|
|
```
|
|
**Example:**
|
|
```bproto
|
|
protocol myCustomAirplaneProtocol version 2
|
|
```
|
|
|
|
The name should identify the protocol in the implementation context (like `robotControlProtocol` or `weatherStationTelemetryDataStream`).
|
|
The version number is used to differentiate between different iterations of the protocol. Different versions of the same protocol are incompatible.
|
|
|
|
For detailed information on naming conventions and versioning strategies, please refer to the [compatibility documentation](/docs/compatibility.md#naming-conventions).
|
|
|
|
## Message
|
|
|
|
A message is a collection of fields that can be serialized and deserialized to be sent over the wire or channel.
|
|
A message should only be a transport container and should not, if possible, be stored permanently.
|
|
|
|
**Syntax:**
|
|
```bproto
|
|
message [<Message ID>] <Message Name> {
|
|
// List of fields
|
|
[<field ID #0>] <field name #0> : <field type #0>,
|
|
[<field ID #1>] <field name #1> : <field type #1>,
|
|
....
|
|
[<field ID #N>] <field name #N> : <field type #N>,
|
|
}
|
|
```
|
|
**Example:**
|
|
```bproto
|
|
message [1] EngineSensorData {
|
|
[0] engine_thrust_left : float32,
|
|
[1] engine_thrust_right : float32,
|
|
[2] fuel_tanks_fill : uint32[8], // Fill levels of 8 fuel tanks
|
|
[3] engine_fault_left : bool,
|
|
[4] engine_fault_right : bool
|
|
}
|
|
```
|
|
|
|
- **Message ID:** Unique identifier within a protocol definition used to differentiate different messages from each other. The Message ID should be between 0 and 255.
|
|
- **Message Name:** Unique name given to this message. This will be used to identify a field in the protocol implementation.
|
|
|
|
### Fields
|
|
A message can have as many fields as necessary. These are comparable to members in a class or fields in a C-struct.
|
|
A field has an `ID`, `Name`, and a `datatype`.
|
|
|
|
**Syntax:**
|
|
`[<ID>] <Name> : <datatype>`
|
|
**Example:**
|
|
``[2] fanSpeed : float32``
|
|
|
|
- **Name:** This is a unique name given to the field. This will be used to identify a field in the protocol implementation.
|
|
- **ID:** A unique identifier used to order the fields in the encoding/decoding. More about serialization can be found [here](/docs/serialization.md#message-field-data-encoding).
|
|
- **datatype:** What type of data to store in this field.
|
|
|
|
### Datatypes
|
|
Datatypes in bproto are independent of language and are translated into the target language-specific type.
|
|
Every Field in a message must have a datatype.
|
|
|
|
Here is a list of datatypes available:
|
|
|
|
| bproto Datatype | Encode Size (bytes) | Python | C | Value Range | Description |
|
|
| --------------- | ------------------- | ------- | ---------- | ------------------------------------------------------- | ---------------------------- |
|
|
| `uint8` | 1 | `int` | `uint8_t` | 0 to 255 | Unsigned 8-bit integer |
|
|
| `uint16` | 2 | `int` | `uint16_t` | 0 to 65,535 | Unsigned 16-bit integer |
|
|
| `uint32` | 4 | `int` | `uint32_t` | 0 to 4,294,967,295 | Unsigned 32-bit integer |
|
|
| `int64` | 8 | `int` | `uint64_t` | 0 to 18,446,744,073,709,551,615 | Unsigned 64-bit integer |
|
|
| `int8` | 1 | `int` | `int8_t` | -128 to 127 | Signed 8-bit integer |
|
|
| `int16` | 2 | `int` | `int16_t` | -32,768 to 32,767 | Signed 16-bit integer |
|
|
| `int32` | 4 | `int` | `int32_t` | -2,147,483,648 to 2,147,483,647 | Signed 32-bit integer |
|
|
| `int64` | 8 | `int` | `int64_t` | -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807 | Signed 64-bit integer |
|
|
| `float32` | 4 | `float` | `float` | 1.2E-38 to 3.4E+38 | 32-bit floating point number |
|
|
| `float64` | 8 | `float` | `double` | 2.3E-308 to 1.7E+308 | 64-bit floating point number |
|
|
| `string[<N>]` | N | `str` | `char[]` | N/A | Fixed-size string |
|
|
| `char` | 1 | `str` | `char` | Single character | Single character |
|
|
| `bool` | 1 | `bool` | `bool` | true or false | Boolean value |
|
|
|
|
Every datatype in this list can be used in a fixed-size array by using this format:
|
|
|
|
**Syntax:**
|
|
`<datatype>[<array_size>]`
|
|
**Example:**
|
|
`float[]`
|
|
|
|
A special case is `string`.
|
|
Strings _must_ be declared as an array because their size must be known from the start.
|
|
|
|
There are also `bits` and `enum` corresponding to **bitfields** and **enums**.
|
|
They are a bit special and are not able to be used as an array.
|
|
Bitfields and enums can be declared inline.
|
|
More details can be found in the sections about [enums](#enumerations) and [bitfields](#bitfields).
|
|
|
|
How different datatypes are encoded can be found [here](/docs/serialization.md#message-field-data-encoding).
|
|
|
|
## Bitfields
|
|
A compact representation of multiple boolean flags within a single byte or group of bytes, optimizing space for binary communication.
|
|
Bitfields are treated as datatypes.
|
|
|
|
**Syntax:**
|
|
```bproto
|
|
bits <bitfield name> {
|
|
<1st bit>, <2nd bit>, ...
|
|
}
|
|
```
|
|
**Example:**
|
|
```bproto
|
|
bits engine_enables {
|
|
engine_left, engine_right
|
|
}
|
|
```
|
|
|
|
Each bit can be either 0 or 1 (true or false), represented as a bool in the target language.
|
|
More details on how Bitfields are encoded in the corresponding language can be found [here](/docs/datatype_language_details.md#bitfields).
|
|
|
|
Bitfields, like Enumerations, can be declared inline in a [message](#message).
|
|
|
|
**Syntax:**
|
|
```bproto
|
|
[<Field ID>] <Field Name> : bits {
|
|
<1st bit>, <2nd bit>, ...
|
|
}
|
|
```
|
|
**Example:**
|
|
```bproto
|
|
[1] lightsEnable: bits {
|
|
Front, Spot, Key, BackLight
|
|
}
|
|
```
|
|
|
|
Bitfield naming when using them inline is found [here](/docs/datatype_language_details.md#inline).
|
|
|
|
## Enumerations
|
|
A set of named integer values that represent discrete states or options.
|
|
Enums enhance code clarity by using descriptive names instead of raw numeric values.
|
|
Enumerations or Enums in bproto are comparable to C or Python enums.
|
|
More details on how Enums are encoded in the corresponding language can be found [here](/docs/datatype_language_details.md#enums).
|
|
Enums are treated as datatypes in bproto.
|
|
|
|
Each Enum item represents a positive (or zero) numeric value.
|
|
These can be implicitly generated by bproto, incrementing by 1.
|
|
The value of the Enum value therefore depends on the declaration order.
|
|
This may lead to bugs and issues when updating one client/receiver's protocol but not the counterparts.
|
|
For more info about this problem, see [here](/docs/serialization.md#message-field-data-encoding).
|
|
|
|
Enum values can also be set explicitly, which eliminates this problem.
|
|
|
|
**Syntax:**
|
|
```bproto
|
|
enum <enum name> {
|
|
<Name #0> (= <Value #0>),
|
|
<Name #1> (= <Value #1>),
|
|
...
|
|
<Name #N> (= <Value #N>),
|
|
}
|
|
```
|
|
**Example:**
|
|
```bproto
|
|
dangerLvl: enum {
|
|
WARNING,
|
|
MELTDOWN,
|
|
ERROR = 10,
|
|
}
|
|
```
|
|
|
|
**Syntax:**
|
|
```bproto
|
|
[<Field ID>] <Field Name> : enum {
|
|
<Name #0> (= <Value #0>),
|
|
<Name #1> (= <Value #1>),
|
|
...
|
|
<Name #N> (= <Value #N>),
|
|
}
|
|
```
|
|
**Example:**
|
|
```bproto
|
|
[6] dangerLvl: enum {
|
|
WARNING,
|
|
MELTDOWN = 5,
|
|
ERROR,
|
|
}
|
|
```
|
|
|
|
Enumeration naming when using them inline is found [here](/docs/datatype_language_details.md#inline).
|
|
|
|
## Comments
|
|
bproto supports C-style comments (with `// ...` and `/* ... */`).
|