1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
// SPDX-FileCopyrightText: Copyright 2025 Au-Zone Technologies
// SPDX-License-Identifier: Apache-2.0
//! One declaration per shared vocabulary, instead of four.
//!
//! `TensorMemory`, `PixelFormat`, and friends each need to agree across the
//! Rust API, the wire protocol, the Python bindings, and the C header. Before
//! this macro, each surface carried its own hand-written numbering of the
//! same variants, and they only agreed by coincidence. `PyTensorMemory` is
//! the live example: its Python enum has no explicit discriminants and a
//! `#[cfg(unix)]` variant sits in the middle of the list, so every variant
//! declared after it silently shifts by one on a non-unix build. Bridging
//! Python and C by integer then hands back `Pbo` where `Mem` was requested,
//! with no error at any layer.
//!
//! [`ef_vocabulary!`] closes that gap structurally: discriminants are
//! mandatory and explicit in the single declaration, so a `cfg`-gated
//! variant keeps its number reserved when it is compiled out, rather than
//! renumbering everything after it. `code()` and the wire module's `const`s
//! are generated from that one declaration, so the Rust enum, the wire
//! encoding, and every other consumer read the same numbers by construction
//! -- there is no second table to fall out of sync.
/// Declare a vocabulary once, emit every surface from it.
///
/// Discriminants are MANDATORY and explicit. A `cfg`-gated variant therefore
/// keeps its number reserved when absent, instead of shifting every variant
/// after it -- which is how `PyTensorMemory` ended up platform-dependent.
///
/// Emits, for a vocabulary `V` with wire module `m`:
/// - `pub enum V` with explicit `#[repr(u32)]` discriminants taken verbatim
/// from the declaration.
/// - `V::code(self) -> u32` (`const fn`) / `V::from_code(u32) -> Option<V>`,
/// the wire numbering. `from_code` returns `None` for an unassigned code
/// rather than guessing at the nearest variant. `code` being `const`
/// lets a consumer that cannot call it directly (a `#[pyclass]`
/// discriminant, which PyO3 requires to be a literal) instead pin its
/// own literal to it with `const _: () = assert!(...)`.
/// - `V::as_str(self) -> &'static str` / `V::from_str_code(&str) -> Option<V>`,
/// the wire string form (not `Debug`, which is free to change).
/// - `V::all() -> &'static [V]`, every variant in declaration order, so
/// cross-surface consistency tests can be exhaustive instead of a sample.
/// - `pub mod m { pub const CONST_NAME: u32 = ...; }`, one `const` per
/// variant, for `const`-only consumers (cbindgen headers, match-free FFI
/// code). This is the shape `protocol::dtype` / `protocol::format` /
/// `protocol::kind` already use by hand. The `mod` clause accepts its own
/// `$(#[meta])*` prefix (e.g. `#[doc(hidden)]`), the same as the `enum`
/// clause does -- `m` has to be `pub` for a *different* module (typically
/// `protocol`) to `pub use` it back out under its real, documented name,
/// so `#[doc(hidden)]` is how a caller marks it as emission plumbing
/// rather than a second, undocumented public API surface for the same
/// vocabulary.
///
/// The wire `const`'s identifier is a separate, explicit field per variant
/// rather than derived from the enum variant name. `DType`'s variants (`U8`,
/// `I8`, ...) happen to already be valid `SCREAMING_SNAKE_CASE`, but
/// `PixelFormat`'s do not -- `PlanarRgb` is the enum variant,
/// `protocol::format::PLANAR_RGB` is the existing wire constant, and no
/// mechanical transform of one produces the other without either an extra
/// dependency for identifier-pasting-with-case-conversion or a hidden
/// word-boundary guessing rule. Spelling both out keeps the same "explicit,
/// not inferred" rule this macro already applies to discriminants.
$*
$modvis:vis mod $modname:ident;
) => ;
}
/// Demo vocabulary exercising [`ef_vocabulary!`] end to end.
///
/// `Beta`'s code (7) is deliberately non-contiguous with `Alpha`'s (0): it
/// proves the discriminant comes from the declaration, not from position in
/// the list. This module carries no real vocabulary -- [`crate::DType`] is
/// converted onto the macro directly (as a proof the macro reproduces
/// today's values unchanged); `PixelFormat` and `TensorMemory` follow in
/// later tasks.