Init Commit: Moved bproto to seperate repo

This commit is contained in:
AlexanderHD27
2025-04-14 14:43:03 +02:00
commit 45bfc724fc
125 changed files with 10822 additions and 0 deletions

221
docs/syntax.md Normal file
View File

@@ -0,0 +1,221 @@
# 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 `/* ... */`).