1use std::{error::Error as StdError, fmt};
2
3#[derive(Debug, Clone, PartialEq, Eq)]
5pub enum CodegenError {
6 OptionalFieldUnsupported { container: String, field: String },
8 DefaultValueUnsupported { container: String, field: String },
10 EnumFieldUnsupported {
12 container: String,
13 field: String,
14 ty: String,
15 },
16 EnumRepresentationUnsupported { enum_name: String, repr: String },
18 EnumVariantValueRequired { enum_name: String, variant: String },
20 EnumVariantValueOutOfRange {
22 enum_name: String,
23 variant: String,
24 value: i64,
25 repr: String,
26 },
27 UnboundedStringUnsupported { container: String, field: String },
29 LegacyMessageUnsupported { packet: String },
31 MessageIdUnsupported { item: String },
33 CommandGroupRequired { packet: String },
35 MissingCommandCode { packet: String },
37 CommandCodeUnsupported { item: String },
39 CommandCodeValueUnsupported { packet: String },
41 CommandCodeOutOfRange { packet: String, value: u64 },
43 DuplicateCommandCodeInGroup {
45 group: String,
46 cc: String,
47 first_packet: String,
48 second_packet: String,
49 },
50 DynamicArrayUnsupported {
52 container: String,
53 field: String,
54 ty: String,
55 },
56 BoundedArrayUnsupported {
58 container: String,
59 field: String,
60 ty: String,
61 },
62}
63
64impl fmt::Display for CodegenError {
65 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
66 match self {
67 CodegenError::OptionalFieldUnsupported { .. }
68 | CodegenError::DefaultValueUnsupported { .. }
69 | CodegenError::UnboundedStringUnsupported { .. }
70 | CodegenError::DynamicArrayUnsupported { .. }
71 | CodegenError::BoundedArrayUnsupported { .. } => fmt_field_error(self, f),
72 CodegenError::EnumFieldUnsupported { .. }
73 | CodegenError::EnumRepresentationUnsupported { .. }
74 | CodegenError::EnumVariantValueRequired { .. }
75 | CodegenError::EnumVariantValueOutOfRange { .. } => fmt_enum_error(self, f),
76 CodegenError::LegacyMessageUnsupported { .. }
77 | CodegenError::MessageIdUnsupported { .. }
78 | CodegenError::CommandGroupRequired { .. } => fmt_packet_error(self, f),
79 CodegenError::MissingCommandCode { .. }
80 | CodegenError::CommandCodeUnsupported { .. }
81 | CodegenError::CommandCodeValueUnsupported { .. }
82 | CodegenError::CommandCodeOutOfRange { .. } => fmt_command_error(self, f),
83 CodegenError::DuplicateCommandCodeInGroup { .. } => fmt_duplicate_error(self, f),
84 }
85 }
86}
87
88fn fmt_field_error(error: &CodegenError, f: &mut fmt::Formatter<'_>) -> fmt::Result {
89 match error {
90 CodegenError::OptionalFieldUnsupported { .. }
91 | CodegenError::DefaultValueUnsupported { .. }
92 | CodegenError::UnboundedStringUnsupported { .. } => fmt_scalar_field_error(error, f),
93 CodegenError::DynamicArrayUnsupported { .. }
94 | CodegenError::BoundedArrayUnsupported { .. } => fmt_array_field_error(error, f),
95 _ => unreachable!("non-field error passed to fmt_field_error"),
96 }
97}
98
99fn fmt_scalar_field_error(error: &CodegenError, f: &mut fmt::Formatter<'_>) -> fmt::Result {
100 match error {
101 CodegenError::OptionalFieldUnsupported { container, field } => write!(
102 f,
103 "optional field `{container}.{field}` is not supported by cFS codegen yet"
104 ),
105 CodegenError::DefaultValueUnsupported { container, field } => write!(
106 f,
107 "default value for field `{container}.{field}` is not supported by cFS codegen yet"
108 ),
109 CodegenError::UnboundedStringUnsupported { container, field } => write!(
110 f,
111 "unbounded string field `{container}.{field}` is not supported by cFS codegen; use `string[<=N]` or `string[N]`"
112 ),
113 _ => unreachable!("non-scalar field error passed to fmt_scalar_field_error"),
114 }
115}
116
117fn fmt_array_field_error(error: &CodegenError, f: &mut fmt::Formatter<'_>) -> fmt::Result {
118 match error {
119 CodegenError::DynamicArrayUnsupported {
120 container,
121 field,
122 ty,
123 } => write!(
124 f,
125 "dynamic array field `{container}.{field}` with type `{ty}` is not supported by cFS codegen yet"
126 ),
127 CodegenError::BoundedArrayUnsupported {
128 container,
129 field,
130 ty,
131 } => write!(
132 f,
133 "bounded array field `{container}.{field}` with type `{ty}` is not supported by cFS codegen yet"
134 ),
135 _ => unreachable!("non-array field error passed to fmt_array_field_error"),
136 }
137}
138
139fn fmt_enum_error(error: &CodegenError, f: &mut fmt::Formatter<'_>) -> fmt::Result {
140 match error {
141 CodegenError::EnumFieldUnsupported {
142 container,
143 field,
144 ty,
145 } => write!(
146 f,
147 "enum field `{container}.{field}` with type `{ty}` needs an explicit integer representation for cFS codegen"
148 ),
149 CodegenError::EnumRepresentationUnsupported { enum_name, repr } => write!(
150 f,
151 "enum `{enum_name}` uses unsupported representation `{repr}`; cFS codegen supports integer enum representations"
152 ),
153 CodegenError::EnumVariantValueRequired { enum_name, variant } => write!(
154 f,
155 "enum `{enum_name}` variant `{variant}` needs an explicit value for cFS codegen"
156 ),
157 CodegenError::EnumVariantValueOutOfRange {
158 enum_name,
159 variant,
160 value,
161 repr,
162 } => write!(
163 f,
164 "enum `{enum_name}` variant `{variant}` value `{value}` does not fit `{repr}`"
165 ),
166 _ => unreachable!("non-enum error passed to fmt_enum_error"),
167 }
168}
169
170fn fmt_packet_error(error: &CodegenError, f: &mut fmt::Formatter<'_>) -> fmt::Result {
171 match error {
172 CodegenError::LegacyMessageUnsupported { packet } => write!(
173 f,
174 "legacy message `{packet}` is not supported by cFS codegen; use `command` or `telemetry`"
175 ),
176 CodegenError::MessageIdUnsupported { item } => write!(
177 f,
178 "`@mid(...)` is not supported on `{item}`; assign its logical topic in the mission manifest"
179 ),
180 CodegenError::CommandGroupRequired { packet } => write!(
181 f,
182 "command `{packet}` must be declared inside a `commands` group"
183 ),
184 _ => unreachable!("non-packet error passed to fmt_packet_error"),
185 }
186}
187
188fn fmt_command_error(error: &CodegenError, f: &mut fmt::Formatter<'_>) -> fmt::Result {
189 match error {
190 CodegenError::MissingCommandCode { packet } => {
191 write!(f, "command `{packet}` is missing required `@cc(...)`")
192 }
193 CodegenError::CommandCodeUnsupported { item } => write!(
194 f,
195 "`@cc(...)` is only supported on command packets, found on `{item}`"
196 ),
197 CodegenError::CommandCodeValueUnsupported { packet } => write!(
198 f,
199 "command `{packet}` has unresolved or non-integer `@cc(...)`; cFS codegen requires an integer, hex, or local integer constant command code"
200 ),
201 CodegenError::CommandCodeOutOfRange { packet, value } => write!(
202 f,
203 "command `{packet}` has function code `{value}` outside the supported `u16` range"
204 ),
205 _ => unreachable!("non-command error passed to fmt_command_error"),
206 }
207}
208
209fn fmt_duplicate_error(error: &CodegenError, f: &mut fmt::Formatter<'_>) -> fmt::Result {
210 match error {
211 CodegenError::DuplicateCommandCodeInGroup {
212 group,
213 cc,
214 first_packet,
215 second_packet,
216 } => write!(
217 f,
218 "duplicate function code `{cc}` in command topic `{group}` used by commands `{first_packet}` and `{second_packet}`"
219 ),
220 _ => unreachable!("non-duplicate error passed to fmt_duplicate_error"),
221 }
222}
223
224impl StdError for CodegenError {}