espforge_diagnostics/codes.rs
1//! The stable diagnostic codes this slice can reach, one per message.
2//!
3//! The ranges are reserved by stage (see the crate docs). A new message gets a
4//! new entry here; the numbers are the legacy ones, never renumbered.
5//!
6//! Codes are data: the human renderer does not print them.
7
8use crate::DiagCode;
9
10macro_rules! codes {
11 ($($(#[$doc:meta])* $name:ident = $code:literal;)*) => {
12 $(
13 $(#[$doc])*
14 pub const $name: DiagCode = DiagCode::new($code);
15 )*
16
17 /// Every code defined in this module, in declaration order.
18 pub const ALL: &[DiagCode] = &[$($name),*];
19 };
20}
21
22codes! {
23 /// A parser-junk line that is not a node.
24 SYNTAX_NODE_LINE = "E0101";
25 /// A line that should have been a `# section` header.
26 SYNTAX_SECTION_HEADER = "E0102";
27 /// Two `# section` blocks with the same name.
28 STRUCTURE_DUPLICATE_SECTION = "E0103";
29 /// A required `# section` block is absent.
30 STRUCTURE_MISSING_SECTION = "E0104";
31 /// A section outside the four-section grammar.
32 STRUCTURE_UNKNOWN_SECTION = "E0105";
33
34 /// An element the `# espforge` schema does not know.
35 CORE_UNKNOWN_ELEMENT = "E0201";
36 /// `# espforge` lacks `<project>`, `<chip>` or `<runtime>`.
37 CORE_INCOMPLETE = "E0202";
38 /// The same element is written twice in `# espforge`.
39 CORE_DUPLICATE_ELEMENT = "E0203";
40 /// `<chip>` without a `type` attribute.
41 CORE_CHIP_WITHOUT_TYPE = "E0204";
42 /// A chip name the catalog does not know.
43 CORE_UNKNOWN_CHIP = "E0205";
44 /// `<runtime>` without a `type` attribute.
45 CORE_RUNTIME_WITHOUT_TYPE = "E0206";
46 /// A runtime name the catalog does not know.
47 CORE_UNKNOWN_RUNTIME = "E0207";
48 /// `<console>` without a `type` attribute.
49 CORE_CONSOLE_WITHOUT_TYPE = "E0208";
50 /// A console name the catalog does not know.
51 CORE_UNKNOWN_CONSOLE = "E0209";
52
53 /// An option name that is not in the schema.
54 OPTION_UNKNOWN = "E0301";
55 /// An option value outside its declared choices.
56 OPTION_INVALID_VALUE = "E0302";
57 /// An option value that cannot be set in `<options>`.
58 OPTION_DERIVED = "E0306";
59 /// An option that needs another option that is off.
60 OPTION_REQUIRES = "E0307";
61 /// An option that the selected chip cannot provide.
62 OPTION_UNAVAILABLE = "E0308";
63 /// Two options in one selection group are on together.
64 OPTION_MUTUALLY_EXCLUSIVE = "E0309";
65 /// The selected console does not exist on the chip.
66 OPTION_NO_CONSOLE = "E0310";
67 /// An attribute value with the wrong type.
68 VALUE_WRONG_TYPE = "E0311";
69 /// A value that should be a boolean.
70 VALUE_NOT_BOOLEAN = "E0312";
71 /// A value that should be an unsigned number.
72 VALUE_NOT_NUMBER = "E0313";
73 /// A key used both as a plain value and as an object.
74 VALUE_KEY_KIND = "E0314";
75 /// A required attribute is absent.
76 VALUE_MISSING_ATTRIBUTE = "E0315";
77
78 /// A peripheral tag no element implements.
79 PERIPHERAL_UNSUPPORTED = "E0501";
80 /// `<gpio pin>` that is not a number.
81 GPIO_INVALID_PIN = "E0502";
82 /// `<gpio direction>` outside `input`/`output`.
83 GPIO_INVALID_DIRECTION = "E0503";
84 /// An `<i2c>` id that is not `i2c0`, `i2c1` or `i2c2`.
85 I2C_INVALID_ID = "E0504";
86 /// An `<i2c>` pin that is not a GPIO number.
87 I2C_INVALID_PIN = "E0505";
88 /// An `<i2c frequency>` that is not `100kHz`-shaped.
89 I2C_INVALID_FREQUENCY = "E0506";
90 /// An `<spi>` id other than `spi2`.
91 SPI_INVALID_ID = "E0507";
92 /// An `<spi>` pin that is not a GPIO number.
93 SPI_INVALID_PIN = "E0508";
94 /// An `<spi mode>` outside 0..=3.
95 SPI_INVALID_MODE = "E0509";
96 /// An `<spi frequency>` that is not `100kHz`-shaped.
97 SPI_INVALID_FREQUENCY = "E0510";
98 /// A `<uart>` id that is not `uart0`..`uart3`.
99 UART_INVALID_ID = "E0511";
100 /// A `<uart uart=>` value outside `UART0`..`UART3`.
101 UART_INVALID_PERIPHERAL = "E0512";
102 /// A `<uart>` pin that is not a GPIO number.
103 UART_INVALID_PIN = "E0513";
104 /// `<uart baud_rate="0">`.
105 UART_INVALID_BAUD = "E0521";
106 /// A `<wifi>` on a chip with no Wi-Fi radio.
107 WIFI_NO_RADIO = "E0514";
108 /// A `<wifi>` whose id is missing or malformed.
109 WIFI_INVALID_ID = "E0515";
110 /// A pin number larger than the chip has.
111 GPIO_NOT_ON_CHIP = "E0516";
112 /// A claim on a pin wired to the SPI flash or PSRAM bus.
113 GPIO_RESERVED_FLASH = "E0517";
114 /// An output claim on an input-only pin.
115 GPIO_NOT_OUTPUT_CAPABLE = "E0518";
116 /// A chip with no pin capability table.
117 PIN_CAPS_MISSING = "E0519";
118 /// A claim on a strapping pin: the level at boot selects a boot mode.
119 GPIO_STRAPPING = "W0520";
120
121 /// An `<led>` that cannot be built.
122 COMPONENT_INVALID_LED = "E0601";
123 /// A `<button>` that cannot be built.
124 COMPONENT_INVALID_BUTTON = "E0602";
125 /// A component tag no element implements.
126 COMPONENT_UNSUPPORTED = "E0606";
127 /// An `<led>` referencing a gpio id that does not exist.
128 COMPONENT_UNKNOWN_GPIO = "E0608";
129 /// A led on an input pin.
130 COMPONENT_WRONG_DIRECTION = "E0609";
131 /// A bus component id that cannot become a Rust identifier.
132 COMPONENT_INVALID_ID = "E0614";
133 /// A recipe component that cannot be built (the recipe's default code).
134 /// Legacy component codes stop at `E0614`; this one is free.
135 COMPONENT_INVALID = "E0615";
136 /// A `<wifi_station wifi>` reference to a radio that does not exist.
137 COMPONENT_UNKNOWN_WIFI = "E0616";
138 /// A second `<wifi_station>` on one `<wifi>` radio.
139 COMPONENT_WIFI_RADIO_USED = "E0617";
140 /// An `ssid` that is empty or longer than 32 bytes.
141 COMPONENT_INVALID_SSID = "E0618";
142 /// A password that is required but missing, or outside 8..=63 characters.
143 COMPONENT_INVALID_PASSWORD = "E0619";
144 /// `auth="open"` written together with a password.
145 COMPONENT_OPEN_WITH_PASSWORD = "E0620";
146 /// A `password="env:NAME"` whose variable name is not an identifier.
147 COMPONENT_INVALID_ENV = "E0621";
148 /// A `<wifi_station>` that cannot be built (missing or invalid attribute).
149 COMPONENT_INVALID_WIFI = "E0622";
150 /// An id the generated code already binds (`devices`, `ctx`, `__x`).
151 COMPONENT_RESERVED_ID = "E0623";
152
153 /// Two elements of different kinds on one pin.
154 CONFLICT_PIN = "E0701";
155 /// A pin claimed by two elements of the same kind.
156 CONFLICT_PIN_USED = "E0702";
157 /// One element needs an input and the other an output.
158 CONFLICT_DIRECTION = "E0703";
159 /// Two elements naming the same hardware peripheral (`UART1`).
160 CONFLICT_PERIPHERAL = "E0704";
161 /// An `<i2c>` that puts sda and scl on one pin.
162 CONFLICT_I2C_WIRING = "E0705";
163 /// An `<spi>` that puts two of its pins on one GPIO.
164 CONFLICT_SPI_WIRING = "E0706";
165 /// A `<uart>` that puts tx and rx on one pin.
166 CONFLICT_UART_WIRING = "E0707";
167 /// Two devices on one `<i2c>` bus sharing an address.
168 CONFLICT_I2C_ADDRESS = "E0708";
169 /// A peripheral the generated runtime already holds (`UART0`).
170 CONFLICT_RUNTIME_HELD = "E0709";
171
172 /// A service `network=` reference to an interface that does not exist.
173 SERVICE_UNKNOWN_NETWORK = "E0801";
174 /// A network service declared under the blocking runtime.
175 SERVICE_REQUIRES_EMBASSY = "E0802";
176 /// A service buffer below the minimum its protocol needs.
177 SERVICE_BUFFER_TOO_SMALL = "E0803";
178 /// `<https_client insecure="true">`: certificates will not be validated.
179 SERVICE_INSECURE_WARNING = "W0804";
180 /// A service that cannot be built: a bad id or a missing attribute.
181 SERVICE_INVALID = "E0805";
182 /// A service tag no element implements.
183 SERVICE_UNSUPPORTED = "E0806";
184 /// A service id the generated code already binds (`services`, `ctx`, ...).
185 SERVICE_RESERVED_ID = "E0807";
186
187 /// A device's bus reference to a component that does not exist.
188 DEVICE_UNKNOWN_COMPONENT = "E0901";
189 /// A device's auxiliary pin reference to a `<gpio>` that does not exist.
190 DEVICE_UNKNOWN_GPIO = "E0902";
191 /// A device's auxiliary pin on a GPIO declared as an input.
192 DEVICE_WRONG_DIRECTION = "E0903";
193 /// A device id that cannot become a Rust identifier.
194 DEVICE_INVALID_ID = "E0904";
195 /// A device tag no element implements.
196 DEVICE_UNSUPPORTED = "E0905";
197 /// A blocking-only display declared under the embassy runtime.
198 DEVICE_REQUIRES_BLOCKING = "E0906";
199 /// A device that cannot be built: a missing or invalid attribute.
200 DEVICE_INVALID = "E0907";
201 /// A device id the generated code already binds (`devices`, `ctx`, ...).
202 DEVICE_RESERVED_ID = "E0908";
203 /// A blocking-only and an async-only driver bound to one bus.
204 DEVICE_BUS_MODE_CONFLICT = "E0909";
205}
206
207#[cfg(test)]
208mod tests {
209 use super::*;
210
211 fn well_formed(code: &str) -> bool {
212 let bytes = code.as_bytes();
213 bytes.len() == 5
214 && matches!(bytes[0], b'E' | b'W')
215 && bytes[1..].iter().all(u8::is_ascii_digit)
216 }
217
218 #[test]
219 fn every_code_is_well_formed() {
220 for code in ALL {
221 assert!(
222 well_formed(code.as_str()),
223 "{} is not `E`/`W` + four digits",
224 code.as_str()
225 );
226 }
227 }
228
229 #[test]
230 fn no_two_codes_share_a_number() {
231 let mut seen = std::collections::BTreeSet::new();
232 for code in ALL {
233 assert!(
234 seen.insert(code.as_str()),
235 "{} is declared twice",
236 code.as_str()
237 );
238 }
239 }
240
241 #[test]
242 fn the_slice_only_defines_the_codes_it_can_reach() {
243 for code in ALL {
244 let number = &code.as_str()[1..];
245 let n: u32 = number.parse().unwrap();
246 assert!(
247 matches!(
248 n,
249 101..=105
250 | 201..=209
251 | 301
252 | 302
253 | 306..=315
254 | 501..=521
255 | 601..=623
256 | 701..=709
257 | 801..=807
258 | 901..=909
259 ),
260 "{} is outside the codes this slice defines",
261 code.as_str()
262 );
263 }
264 }
265}