Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/COMPARISON-TABLES.md
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ the source list at the end.
| Declared numeric bounds | `\| min, max` in the type; bits on the type wire, clamp and count on the table wire (SPEC §4.3, §4) | — | — |
| Fixed point | `fixed(I,F)`, `ufixed(I,F)`, exact round trip on both wires (SPEC §4.3; SPEC-TABLES §3, §16.2) | — | — |
| Constants | `const`, typed or inferred, exported to every language, usable in bounds and extents | — | — |
| Enums | implicit `None = 0`, dense from 1, `Max`; on the table wire a value rides as the hash of its name (§3) | explicit values on a declared integer type; `bit_flags` (FB-schema) | 32-bit values, first must be 0, aliases, reserved values, open or closed per edition (PB-enum) |
| Enums | implicit `None = 0`, dense from 1, `Count` and `Max`; on the table wire a value rides as the hash of its name (§3) | explicit values on a declared integer type; `bit_flags` (FB-schema) | 32-bit values, first must be 0, aliases, reserved values, open or closed per edition (PB-enum) |
| Flags | `flags`, up to 64 bits, `uint64` storage everywhere, `.Count`; rides as a mask (§3) | `enum (bit_flags)` | — |
| Inline struct | a `type` nested by value; a whole fixed table is a plain struct (§2.2, §6.1) | `struct`: scalars and structs only, inline, unversioned (FB-internals) | — ; every message is length-delimited (PB-encoding) |
| Nested composites | tables nest by value; a by-value cycle is refused naming it (§2) | tables by offset; depth bounded by the verifier's `max_depth` (FB-cpp) | unlimited nesting; parser recursion limit 100 (PB-limits) |
Expand Down
35 changes: 29 additions & 6 deletions docs/SPEC.md
Original file line number Diff line number Diff line change
Expand Up @@ -452,13 +452,20 @@ FloatExpr = float expression over float literals, int literals and const names
the reserved values above the last variant are wire-legal and name no slot.
It works on the generated tag set
too (a union's `<Union>Type.Max` — §4.8); generated sets resolve in
constant expressions and nowhere else. **Flags
constant expressions and nowhere else.
- **Declared-count references:** **`.Count`** in any integer expression names
the DECLARED variant count of an enum or a flags declaration — one word
meaning one thing in both. `E.Count` excludes an enum's implicit `None`;
`F.Count` counts the named bits. Under `| max = K` headroom the count and
the extent part — an enum's `Max` is the widened extent and a flags
declaration's wire width is K, while `Count` stays the count — and without
headroom `E.Count` equals `E.Max`. `[..E.Count]T` is therefore a counted
array over the declared variants, where `[E.Max]T` is the keyed array with
one slot per admitted ordinal. **Flags
have `F.Count`, not `F.Max`** — a flags declaration is a set of
independent bits, not a range with a top, so max-of-what is exactly the
confusion `.Max` would invite and the compiler refuses it naming the
split. `F.Count` is the DECLARED variant count; under `| max = K` headroom
the wire width is K while `Count` stays the count — the one case the two
numbers diverge. `Max` and `Count` after `.` are contextual, like
split. `Max` and `Count` after `.` are contextual, like
attribute keys; the lexer keeps maximal munch, so `..` still wins over
`.`.
- **Constants are platform-uniform.** A schema has no platform conditionals.
Expand Down Expand Up @@ -711,7 +718,8 @@ a language rule — the language does not enforce entry 0's meaning.
enum and the generated `<Union>Type` tag enums — carries its
extent as a member named `Max` in the target's own convention: `E::Max`
(C++), `E.Max` (C#), `EMax` (Go), `E::MAX` (Rust), `E.Max` (JS), `E_MAX`
(C). Its value is the enum's max — the same number `E.Max` names in schema
(C), `E.max` (Dart and Java), `E.max/0` (Elixir). Its value is the enum's
max — the same number `E.Max` names in schema
expressions (§4.2): the highest wire-legal value, which under the
sentinel-zero convention is the count of real variants when no `max`
headroom widens it. Application code states ranges and asserts directly
Expand All @@ -721,6 +729,20 @@ constant that re-derives it. `Max` is therefore a reserved variant name —
declaring a variant named `Max` is refused at check time, exactly as `None`
is.

**The declared count is exported too.** Every declared enum carries its
**`Count`** beside its `Max`: the number of DECLARED variants, excluding the
implicit `None`. It is the same number `E.Count` names in schema expressions
(§4.2), it equals `Max` when no `| max = K` headroom widens the enum, and it
is below `Max` when one does — which is the whole reason it is exported. All
nine targets spell it their own way, the spelling each already uses for a
flags declaration's `Count`: `E::Count` (C++), `E.Count` (C#), `ECount`
(Go), `E::COUNT` (Rust), `E.Count` (JS), `E_COUNT` (C), `E.count` (Dart and
Java), `E.count/0` (Elixir). `Count` is a reserved variant name for the same
reason `Max` is, and it is a claimed name under §4.6 — a declaration whose
generated symbol would collide with an enum's `Count` is refused, naming the
enum. The generated `<Union>Type` tag enums carry `Max` alone: a tag set
takes no headroom, so its count and its extent are one number.

### 4.3 Field types and their wire encodings

**The wire model — normative:**
Expand Down Expand Up @@ -912,7 +934,8 @@ All compile errors with positions:
and no unit declares `ProtocolId`. The checker likewise refuses user names
that collide with per-declaration generated symbols
(`Write*`/`Read*`/`New*`, `*MaxBits`/`*MaxBytes`, companion length/count
names, a union's generated tag surface). Diagnostics name the generated
names, an enum's `Max` and `Count`, a flags declaration's `Count`, a
union's generated tag surface). Diagnostics name the generated
artifact that claims the name.
- Enum `| max = K` below the variant count.
- **Duplicate field names anywhere in one type — including across branch
Expand Down
26 changes: 23 additions & 3 deletions docs/USAGE.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,11 +112,14 @@ zero-initialized enum field is therefore the null, in band, and you never
need a separate has-flag beside it:

```cpp
enum class ShipType : uint8_t { None = 0, Fighter = 1, Corvette = 2, Bomber = 3, Max = 3 };
enum class ShipType : uint8_t { None = 0, Fighter = 1, Corvette = 2, Bomber = 3, Count = 3, Max = 3 };
```

On the wire it costs `bitsRequired(variant count)` — 2 bits here, for four
values. Declaring `enum E | max = 15` (its variant list on the next line) reserves
values. `None` is one of those values, so an enum whose declared variant
count is a power of two pays one bit for it: four declared variants are five
wire values and cost 3 bits, not 2. Declaring `enum E | max = 15` (its variant
list on the next line) reserves
headroom so you can
add variants later without moving the field width.

Expand All @@ -131,6 +134,22 @@ carries it too, so ranges and asserts reference the enum directly instead of
a hand-declared count constant. `Max` is consequently reserved as a variant
name, like `None`.

The `Count` member beside it is the **declared variant count**, `None`
excluded — `ShipType::Count` (C++), `ShipType.Count` (C#), `ShipTypeCount`
(Go), `ShipType::COUNT` (Rust), `ShipType.Count` (JS), `SHIP_TYPE_COUNT` (C),
`ShipType.count` (Dart and Java), `ShipType.count/0` (Elixir), and
`E.Count` in schema expressions. Without headroom `Count` and `Max` are the
same number; under `| max = 15` they are 3 and 15, and that difference is
what the two words are for. `Count` is a reserved variant name too.

**Two loop rules, and they are the whole story:**

- A loop over the **declared variants** runs from `1` to `Count` inclusive.
- A loop over **every ordinal**, `None` included, runs from `0` to `Max`
inclusive.
- **Size storage and keyed arrays by `Max`** — the extent is what has to fit,
headroom and all.

Every target also generates a **debug/log name function**, and the spelling is
each target's own: `EnumName(value)` in C++ (overloaded per enum),
`EnumNameShipType` in C#/Go/JS, `enumNameShipType` in Dart/Java, and
Expand All @@ -156,7 +175,8 @@ inline constexpr int64_t CapabilitiesCount = 3;
```

The declared variant count is exported as `Count` and usable in schema
expressions as `Capabilities.Count`. Flags have no `.Max` — the variants are
expressions as `Capabilities.Count` — the same word an enum carries, meaning
the same thing. Flags have no `.Max` — the variants are
independent bits, not a range with a top; the compiler refuses `.Max` on a
flags type and names `.Count` instead.

Expand Down
1 change: 1 addition & 0 deletions generated/bench/c/Bench.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ typedef uint8_t MixedWeapon;
#define MIXED_WEAPON_TURRET 13
#define MIXED_WEAPON_DRONE 14
#define MIXED_WEAPON_REPAIR 15
#define MIXED_WEAPON_COUNT 15
#define MIXED_WEAPON_MAX 15

/* Debug/log name for any MixedWeapon value, out-of-set included. */
Expand Down
1 change: 1 addition & 0 deletions generated/bench/c/RealWorld.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ typedef uint8_t PacketMode;
#define PACKET_MODE_COMBAT 3
#define PACKET_MODE_DOCKED 4
#define PACKET_MODE_WARPING 5
#define PACKET_MODE_COUNT 5
#define PACKET_MODE_MAX 5

/* Debug/log name for any PacketMode value, out-of-set included. */
Expand Down
1 change: 1 addition & 0 deletions generated/bench/cpp/Bench.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ enum class MixedWeapon : uint8_t {
Turret = 13,
Drone = 14,
Repair = 15,
Count = 15, // the declared variant count (SPEC §4.2)
Max = 15, // the exported extent (SPEC §4.2)
};

Expand Down
1 change: 1 addition & 0 deletions generated/bench/cpp/RealWorld.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ enum class PacketMode : uint8_t {
Combat = 3,
Docked = 4,
Warping = 5,
Count = 5, // the declared variant count (SPEC §4.2)
Max = 5, // the exported extent (SPEC §4.2)
};

Expand Down
1 change: 1 addition & 0 deletions generated/bench/cs/Bench.cs
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ public enum MixedWeapon : byte
Turret = 13,
Drone = 14,
Repair = 15,
Count = 15, // the declared variant count (SPEC §4.2)
Max = 15, // the exported extent (SPEC §4.2)
}

Expand Down
1 change: 1 addition & 0 deletions generated/bench/cs/realworld/RealWorld.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ public enum PacketMode : byte
Combat = 3,
Docked = 4,
Warping = 5,
Count = 5, // the declared variant count (SPEC §4.2)
Max = 5, // the exported extent (SPEC §4.2)
}

Expand Down
1 change: 1 addition & 0 deletions generated/bench/dart/Bench.dart
Original file line number Diff line number Diff line change
Expand Up @@ -777,6 +777,7 @@ abstract final class MixedWeapon {
static const int turret = 13;
static const int drone = 14;
static const int repair = 15;
static const int count = 15; // the declared variant count (SPEC §4.2)
static const int max = 15; // the exported extent (SPEC §4.2)
}

Expand Down
1 change: 1 addition & 0 deletions generated/bench/dart/realworld/RealWorld.dart
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ abstract final class PacketMode {
static const int combat = 3;
static const int docked = 4;
static const int warping = 5;
static const int count = 5; // the declared variant count (SPEC §4.2)
static const int max = 5; // the exported extent (SPEC §4.2)
}

Expand Down
2 changes: 2 additions & 0 deletions generated/bench/elixir/Bench.ex
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,8 @@ defmodule Bench.MixedWeapon do
def turret, do: 13
def drone, do: 14
def repair, do: 15
# the declared variant count (SPEC §4.2)
def count, do: 15
# the exported extent (SPEC §4.2)
def max, do: 15
end
Expand Down
2 changes: 2 additions & 0 deletions generated/bench/elixir/realworld/RealWorld.ex
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ defmodule Realworld.PacketMode do
def combat, do: 3
def docked, do: 4
def warping, do: 5
# the declared variant count (SPEC §4.2)
def count, do: 5
# the exported extent (SPEC §4.2)
def max, do: 5
end
Expand Down
1 change: 1 addition & 0 deletions generated/bench/go/Bench.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions generated/bench/go/realworld/RealWorld.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions generated/bench/java/Bench.java
Original file line number Diff line number Diff line change
Expand Up @@ -1049,6 +1049,8 @@ private MixedWeapon() {}
public static final byte turret = 13;
public static final byte drone = 14;
public static final byte repair = 15;
// the declared variant count (SPEC §4.2)
public static final byte count = 15;
// the exported extent (SPEC §4.2)
public static final byte max = 15;
}
Expand Down
2 changes: 2 additions & 0 deletions generated/bench/java/realworld/RealWorld.java
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ private PacketMode() {}
public static final byte combat = 3;
public static final byte docked = 4;
public static final byte warping = 5;
// the declared variant count (SPEC §4.2)
public static final byte count = 5;
// the exported extent (SPEC §4.2)
public static final byte max = 5;
}
Expand Down
1 change: 1 addition & 0 deletions generated/bench/js/Bench.js
Original file line number Diff line number Diff line change
Expand Up @@ -456,6 +456,7 @@ export const MixedWeapon = Object.freeze({
Turret: 13,
Drone: 14,
Repair: 15,
Count: 15, // the declared variant count (SPEC §4.2)
Max: 15, // the exported extent (SPEC §4.2)
});

Expand Down
1 change: 1 addition & 0 deletions generated/bench/js/realworld/RealWorld.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ export const PacketMode = Object.freeze({
Combat: 3,
Docked: 4,
Warping: 5,
Count: 5, // the declared variant count (SPEC §4.2)
Max: 5, // the exported extent (SPEC §4.2)
});

Expand Down
1 change: 1 addition & 0 deletions generated/bench/rust-realworld/src/realworld.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ impl PacketMode {
pub const COMBAT: PacketMode = PacketMode(3);
pub const DOCKED: PacketMode = PacketMode(4);
pub const WARPING: PacketMode = PacketMode(5);
pub const COUNT: PacketMode = PacketMode(5); // the declared variant count (SPEC §4.2)
pub const MAX: PacketMode = PacketMode(5); // the exported extent (SPEC §4.2)
}

Expand Down
1 change: 1 addition & 0 deletions generated/bench/rust/src/bench.rs
Original file line number Diff line number Diff line change
Expand Up @@ -459,6 +459,7 @@ impl MixedWeapon {
pub const TURRET: MixedWeapon = MixedWeapon(13);
pub const DRONE: MixedWeapon = MixedWeapon(14);
pub const REPAIR: MixedWeapon = MixedWeapon(15);
pub const COUNT: MixedWeapon = MixedWeapon(15); // the declared variant count (SPEC §4.2)
pub const MAX: MixedWeapon = MixedWeapon(15); // the exported extent (SPEC §4.2)
}

Expand Down
1 change: 1 addition & 0 deletions generated/bench/tables/c/BenchTable.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ typedef uint8_t TableWeapon;
#define TABLE_WEAPON_TURRET 13
#define TABLE_WEAPON_DRONE 14
#define TABLE_WEAPON_REPAIR 15
#define TABLE_WEAPON_COUNT 15
#define TABLE_WEAPON_MAX 15

/* Debug/log name for any TableWeapon value, out-of-set included. */
Expand Down
1 change: 1 addition & 0 deletions generated/bench/tables/cpp/BenchTable.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ enum class TableWeapon : uint8_t {
Turret = 13,
Drone = 14,
Repair = 15,
Count = 15, // the declared variant count (SPEC §4.2)
Max = 15, // the exported extent (SPEC §4.2)
};

Expand Down
1 change: 1 addition & 0 deletions generated/bench/tables/cs/BenchTable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ public enum TableWeapon : byte
Turret = 13,
Drone = 14,
Repair = 15,
Count = 15, // the declared variant count (SPEC §4.2)
Max = 15, // the exported extent (SPEC §4.2)
}

Expand Down
1 change: 1 addition & 0 deletions generated/bench/tables/dart/BenchTable.dart
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ abstract final class TableWeapon {
static const int turret = 13;
static const int drone = 14;
static const int repair = 15;
static const int count = 15; // the declared variant count (SPEC §4.2)
static const int max = 15; // the exported extent (SPEC §4.2)
}

Expand Down
2 changes: 2 additions & 0 deletions generated/bench/tables/elixir/BenchTable.ex
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ defmodule Benchtable.TableWeapon do
def turret, do: 13
def drone, do: 14
def repair, do: 15
# the declared variant count (SPEC §4.2)
def count, do: 15
# the exported extent (SPEC §4.2)
def max, do: 15
end
Expand Down
1 change: 1 addition & 0 deletions generated/bench/tables/go/BenchTable.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions generated/bench/tables/java/BenchTable.java
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ private TableWeapon() {}
public static final byte turret = 13;
public static final byte drone = 14;
public static final byte repair = 15;
// the declared variant count (SPEC §4.2)
public static final byte count = 15;
// the exported extent (SPEC §4.2)
public static final byte max = 15;
}
Expand Down
1 change: 1 addition & 0 deletions generated/bench/tables/js/BenchTable.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ export const TableWeapon = Object.freeze({
Turret: 13,
Drone: 14,
Repair: 15,
Count: 15, // the declared variant count (SPEC §4.2)
Max: 15, // the exported extent (SPEC §4.2)
});

Expand Down
1 change: 1 addition & 0 deletions generated/bench/tables/rust/src/benchtable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ impl TableWeapon {
pub const TURRET: TableWeapon = TableWeapon(13);
pub const DRONE: TableWeapon = TableWeapon(14);
pub const REPAIR: TableWeapon = TableWeapon(15);
pub const COUNT: TableWeapon = TableWeapon(15); // the declared variant count (SPEC §4.2)
pub const MAX: TableWeapon = TableWeapon(15); // the exported extent (SPEC §4.2)
}

Expand Down
1 change: 1 addition & 0 deletions generated/c-ludicrous/Ludicrous.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ typedef uint8_t DriveMode;
#define DRIVE_MODE_CRUISE 1
#define DRIVE_MODE_WARP 2
#define DRIVE_MODE_LUDICROUS 3
#define DRIVE_MODE_COUNT 3
#define DRIVE_MODE_MAX 3

/* Debug/log name for any DriveMode value, out-of-set included. */
Expand Down
5 changes: 5 additions & 0 deletions generated/c/Enums.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ typedef uint8_t Team;
#define TEAM_NONE 0
#define TEAM_RED 1
#define TEAM_BLUE 2
#define TEAM_COUNT 2
#define TEAM_MAX 2

/* Debug/log name for any Team value, out-of-set included. */
Expand All @@ -56,6 +57,7 @@ typedef uint8_t ShipType;
#define SHIP_TYPE_BOMBER 3
#define SHIP_TYPE_DESTROYER 4
#define SHIP_TYPE_CARRIER 5
#define SHIP_TYPE_COUNT 5
#define SHIP_TYPE_MAX 5

/* Debug/log name for any ShipType value, out-of-set included. */
Expand Down Expand Up @@ -83,6 +85,7 @@ typedef uint8_t MissileType;
#define MISSILE_TYPE_HEATSEEKER 1
#define MISSILE_TYPE_TORPEDO 2
#define MISSILE_TYPE_NUKE 3
#define MISSILE_TYPE_COUNT 3
#define MISSILE_TYPE_MAX 3

/* Debug/log name for any MissileType value, out-of-set included. */
Expand Down Expand Up @@ -111,6 +114,7 @@ typedef uint8_t PropType;
#define PROP_TYPE_SPHERE 4
#define PROP_TYPE_BLACK_HOLE 5
#define PROP_TYPE_DYSON_PANEL 6
#define PROP_TYPE_COUNT 6
#define PROP_TYPE_MAX 6

/* Debug/log name for any PropType value, out-of-set included. */
Expand All @@ -136,6 +140,7 @@ static SCHEMA_UNUSED const char * enum_name_prop_type( PropType value )
values wire-legal, which a C enum cannot hold honestly. */
typedef uint8_t Pending;
#define PENDING_NONE 0
#define PENDING_COUNT 0
#define PENDING_MAX 0

/* Debug/log name for any Pending value, out-of-set included. */
Expand Down
Loading
Loading