Skip to main content

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
32    /// An element the `# espforge` schema does not know.
33    CORE_UNKNOWN_ELEMENT = "E0201";
34    /// `# espforge` lacks `<project>`, `<chip>` or `<runtime>`.
35    CORE_INCOMPLETE = "E0202";
36    /// The same element is written twice in `# espforge`.
37    CORE_DUPLICATE_ELEMENT = "E0203";
38    /// `<chip>` without a `type` attribute.
39    CORE_CHIP_WITHOUT_TYPE = "E0204";
40    /// A chip name the catalog does not know.
41    CORE_UNKNOWN_CHIP = "E0205";
42    /// `<runtime>` without a `type` attribute.
43    CORE_RUNTIME_WITHOUT_TYPE = "E0206";
44    /// A runtime name the catalog does not know.
45    CORE_UNKNOWN_RUNTIME = "E0207";
46    /// `<console>` without a `type` attribute.
47    CORE_CONSOLE_WITHOUT_TYPE = "E0208";
48    /// A console name the catalog does not know.
49    CORE_UNKNOWN_CONSOLE = "E0209";
50
51    /// An option name that is not in the schema.
52    OPTION_UNKNOWN = "E0301";
53    /// An option value outside its declared choices.
54    OPTION_INVALID_VALUE = "E0302";
55    /// An option value that cannot be set in `<options>`.
56    OPTION_DERIVED = "E0306";
57    /// An option that needs another option that is off.
58    OPTION_REQUIRES = "E0307";
59    /// An option that the selected chip cannot provide.
60    OPTION_UNAVAILABLE = "E0308";
61    /// Two options in one selection group are on together.
62    OPTION_MUTUALLY_EXCLUSIVE = "E0309";
63    /// The selected console does not exist on the chip.
64    OPTION_NO_CONSOLE = "E0310";
65    /// An attribute value with the wrong type.
66    VALUE_WRONG_TYPE = "E0311";
67    /// A value that should be a boolean.
68    VALUE_NOT_BOOLEAN = "E0312";
69    /// A value that should be an unsigned number.
70    VALUE_NOT_NUMBER = "E0313";
71    /// A key used both as a plain value and as an object.
72    VALUE_KEY_KIND = "E0314";
73    /// A required attribute is absent.
74    VALUE_MISSING_ATTRIBUTE = "E0315";
75
76    /// A peripheral tag no element implements.
77    PERIPHERAL_UNSUPPORTED = "E0501";
78    /// `<gpio pin>` that is not a number.
79    GPIO_INVALID_PIN = "E0502";
80    /// `<gpio direction>` outside `input`/`output`.
81    GPIO_INVALID_DIRECTION = "E0503";
82    /// An `<i2c>` id that is not `i2c0`, `i2c1` or `i2c2`.
83    I2C_INVALID_ID = "E0504";
84    /// An `<i2c>` pin that is not a GPIO number.
85    I2C_INVALID_PIN = "E0505";
86    /// An `<i2c frequency>` that is not `100kHz`-shaped.
87    I2C_INVALID_FREQUENCY = "E0506";
88    /// An `<spi>` id other than `spi2`.
89    SPI_INVALID_ID = "E0507";
90    /// An `<spi>` pin that is not a GPIO number.
91    SPI_INVALID_PIN = "E0508";
92    /// An `<spi mode>` outside 0..=3.
93    SPI_INVALID_MODE = "E0509";
94    /// An `<spi frequency>` that is not `100kHz`-shaped.
95    SPI_INVALID_FREQUENCY = "E0510";
96    /// A `<uart>` id that is not `uart0`..`uart3`.
97    UART_INVALID_ID = "E0511";
98    /// A `<uart uart=>` value outside `UART0`..`UART3`.
99    UART_INVALID_PERIPHERAL = "E0512";
100    /// A `<uart>` pin that is not a GPIO number.
101    UART_INVALID_PIN = "E0513";
102    /// A `<wifi>` on a chip with no Wi-Fi radio.
103    WIFI_NO_RADIO = "E0514";
104    /// A `<wifi>` whose id is missing or malformed.
105    WIFI_INVALID_ID = "E0515";
106
107    /// An `<led>` that cannot be built.
108    COMPONENT_INVALID_LED = "E0601";
109    /// A `<button>` that cannot be built.
110    COMPONENT_INVALID_BUTTON = "E0602";
111    /// An `<i2c_component>` that cannot be built.
112    COMPONENT_INVALID_I2C = "E0603";
113    /// An `<spi_component>` that cannot be built.
114    COMPONENT_INVALID_SPI = "E0604";
115    /// A `<uart_component>` that cannot be built.
116    COMPONENT_INVALID_UART = "E0605";
117    /// A component tag no element implements.
118    COMPONENT_UNSUPPORTED = "E0606";
119    /// An `<spi_component cs>` naming a gpio that does not exist.
120    COMPONENT_INVALID_CS = "E0607";
121    /// An `<led>` referencing a gpio id that does not exist.
122    COMPONENT_UNKNOWN_GPIO = "E0608";
123    /// A led on an input pin.
124    COMPONENT_WRONG_DIRECTION = "E0609";
125    /// A `<uart_component baud_rate="0">`.
126    COMPONENT_INVALID_BAUD = "E0610";
127    /// A second `<uart_component>` on one `<uart>` port.
128    COMPONENT_UART_USED = "E0612";
129    /// A bus component referring to a bus that does not exist.
130    COMPONENT_UNKNOWN_BUS = "E0613";
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
151    /// Two elements of different kinds on one pin.
152    CONFLICT_PIN = "E0701";
153    /// A pin claimed by two elements of the same kind.
154    CONFLICT_PIN_USED = "E0702";
155    /// One element needs an input and the other an output.
156    CONFLICT_DIRECTION = "E0703";
157    /// Two elements naming the same hardware peripheral (`UART1`).
158    CONFLICT_PERIPHERAL = "E0704";
159    /// An `<i2c>` that puts sda and scl on one pin.
160    CONFLICT_I2C_WIRING = "E0705";
161    /// An `<spi>` that puts two of its pins on one GPIO.
162    CONFLICT_SPI_WIRING = "E0706";
163    /// A `<uart>` that puts tx and rx on one pin.
164    CONFLICT_UART_WIRING = "E0707";
165    /// Two addressed `<i2c_component>`s on one `<i2c>` bus sharing an address.
166    CONFLICT_I2C_ADDRESS = "E0708";
167
168    /// A service `network=` reference to an interface that does not exist.
169    SERVICE_UNKNOWN_NETWORK = "E0801";
170    /// A network service declared under the blocking runtime.
171    SERVICE_REQUIRES_EMBASSY = "E0802";
172    /// A service buffer below the minimum its protocol needs.
173    SERVICE_BUFFER_TOO_SMALL = "E0803";
174    /// `<https_client insecure="true">`: certificates will not be validated.
175    SERVICE_INSECURE_WARNING = "W0804";
176    /// A service that cannot be built: a bad id or a missing attribute.
177    SERVICE_INVALID = "E0805";
178    /// A service tag no element implements.
179    SERVICE_UNSUPPORTED = "E0806";
180
181    /// A device's bus reference to a component that does not exist.
182    DEVICE_UNKNOWN_COMPONENT = "E0901";
183    /// A device's auxiliary pin reference to a `<gpio>` that does not exist.
184    DEVICE_UNKNOWN_GPIO = "E0902";
185    /// A device's auxiliary pin on a GPIO declared as an input.
186    DEVICE_WRONG_DIRECTION = "E0903";
187    /// A device id that cannot become a Rust identifier.
188    DEVICE_INVALID_ID = "E0904";
189    /// A device tag no element implements.
190    DEVICE_UNSUPPORTED = "E0905";
191    /// A blocking-only display declared under the embassy runtime.
192    DEVICE_REQUIRES_BLOCKING = "E0906";
193    /// A device that cannot be built: a missing or invalid attribute.
194    DEVICE_INVALID = "E0907";
195}
196
197#[cfg(test)]
198mod tests {
199    use super::*;
200
201    fn well_formed(code: &str) -> bool {
202        let bytes = code.as_bytes();
203        bytes.len() == 5
204            && matches!(bytes[0], b'E' | b'W')
205            && bytes[1..].iter().all(u8::is_ascii_digit)
206    }
207
208    #[test]
209    fn every_code_is_well_formed() {
210        for code in ALL {
211            assert!(
212                well_formed(code.as_str()),
213                "{} is not `E`/`W` + four digits",
214                code.as_str()
215            );
216        }
217    }
218
219    #[test]
220    fn no_two_codes_share_a_number() {
221        let mut seen = std::collections::BTreeSet::new();
222        for code in ALL {
223            assert!(
224                seen.insert(code.as_str()),
225                "{} is declared twice",
226                code.as_str()
227            );
228        }
229    }
230
231    #[test]
232    fn the_slice_only_defines_the_codes_it_can_reach() {
233        for code in ALL {
234            let number = &code.as_str()[1..];
235            let n: u32 = number.parse().unwrap();
236            assert!(
237                matches!(
238                    n,
239                    101..=104
240                        | 201..=209
241                        | 301
242                        | 302
243                        | 306..=315
244                        | 501..=515
245                        | 601..=622
246                        | 701..=708
247                        | 801..=806
248                        | 901..=907
249                ),
250                "{} is outside the codes this slice defines",
251                code.as_str()
252            );
253        }
254    }
255}