aion_package/declared_command/error.rs
1//! The refusals a render earns, one per honest way a parameter set and a
2//! declared command can fail to meet.
3
4use thiserror::Error;
5
6/// Why a declared command could not be rendered into an argv.
7///
8/// Every variant is TERMINAL for an executing action: the same parameter set
9/// against the same declaration fails identically however many times it is
10/// retried. The AWL side maps each of these back onto its own cause
11/// vocabulary with a source span; an executor reports the message as it
12/// stands.
13#[derive(Clone, Debug, PartialEq, Eq, Error)]
14pub enum RenderError {
15 /// The parameter set names something the command does not declare.
16 #[error(
17 "the parameter set names `{parameter}`, which command `{command}` does not declare; a \
18 value nothing consumes is a value nobody reviewed"
19 )]
20 ArgumentUndeclared {
21 /// The command being rendered.
22 command: String,
23 /// The undeclared name that was supplied.
24 parameter: String,
25 },
26 /// A declared parameter has neither a supplied value nor a default.
27 #[error(
28 "the parameter set omits `{parameter}`, which command `{command}` declares and gives no \
29 default; there is nothing for this surface to invent"
30 )]
31 ArgumentMissing {
32 /// The command being rendered.
33 command: String,
34 /// The parameter nothing filled.
35 parameter: String,
36 },
37 /// A supplied value's shape does not match the parameter's declared type.
38 #[error(
39 "parameter `{parameter}` of command `{command}` is declared a {declared}, and the \
40 parameter set supplies a {supplied}"
41 )]
42 ArgumentTypeMismatch {
43 /// The command being rendered.
44 command: String,
45 /// The parameter whose shape did not match.
46 parameter: String,
47 /// The value that was supplied, as a diagnostic reads it. Carried
48 /// rather than re-derived: the bytes a reader must be handed are the
49 /// ones that were actually seen.
50 observed: String,
51 /// The declared shape, as a diagnostic reads it.
52 declared: &'static str,
53 /// The supplied shape, as a diagnostic reads it.
54 supplied: &'static str,
55 },
56 /// An operand would emit leading-dash bytes into a position the program
57 /// is still reading options in, with no end-of-options marker before it.
58 #[error(
59 "command `{command}` would emit `{element}` for argument `{argument}`, which begins with \
60 `-`, and no `{marker}` argument stands before it. Nothing downstream could tell it from \
61 an option"
62 )]
63 LeadingDashOperand {
64 /// The command being rendered.
65 command: String,
66 /// How the declaration names the offending argument.
67 argument: String,
68 /// The element that would have been emitted.
69 element: String,
70 /// The end-of-options marker the declaration could have carried.
71 marker: &'static str,
72 },
73 /// A supplied value has no unambiguous argument form.
74 #[error(
75 "parameter `{parameter}` is {kind}, which has no unambiguous command-argument form; \
76 supply a string, number, or boolean"
77 )]
78 UnrepresentableValue {
79 /// The parameter whose value could not be rendered.
80 parameter: String,
81 /// The JSON kind that was supplied.
82 kind: &'static str,
83 },
84 /// A supplied string contains a NUL byte.
85 ///
86 /// Refused rather than truncated: an argument reaches the kernel as a
87 /// NUL-terminated string, so a NUL inside a value would silently cut the
88 /// argument short and change what the program receives.
89 #[error(
90 "parameter `{parameter}` contains a NUL byte, which cannot appear in a command argument"
91 )]
92 InteriorNul {
93 /// The parameter whose value carried the NUL.
94 parameter: String,
95 },
96}
97
98/// How a diagnostic names a value shape.
99#[must_use]
100pub const fn shape_word(list: bool) -> &'static str {
101 if list { "list" } else { "single value" }
102}