target_spec_miette/
imp.rs1use miette::{Diagnostic, LabeledSpan, SourceCode, SourceOffset, SourceSpan};
5use std::{error::Error as StdError, fmt};
6use target_spec::errors::{
7 CustomTripleCreateError, Error as TargetSpecError, ExpressionParseError, PlainStringParseError,
8 RustcVersionVerboseParseError, TripleParseError,
9};
10
11pub trait IntoMietteDiagnostic {
13 type IntoDiagnostic;
15
16 fn into_diagnostic(self) -> Self::IntoDiagnostic;
20}
21
22impl IntoMietteDiagnostic for TargetSpecError {
23 type IntoDiagnostic = Box<dyn Diagnostic + Send + Sync + 'static>;
24
25 fn into_diagnostic(self) -> Self::IntoDiagnostic {
26 match self {
27 Self::InvalidExpression(error) => Box::new(error.into_diagnostic()),
28 Self::InvalidTargetSpecString(error) => Box::new(error.into_diagnostic()),
29 Self::UnknownPlatformTriple(error) => Box::new(error.into_diagnostic()),
30 #[allow(deprecated)]
31 Self::CustomTripleCreate(error) => Box::new(error.into_diagnostic()),
32 Self::CustomPlatformCreate(error) => Box::new(error.into_diagnostic()),
33 Self::RustcVersionVerboseParse(error) => Box::new(error.into_diagnostic()),
34 other => Box::<dyn Diagnostic + Send + Sync + 'static>::from(other.to_string()),
35 }
36 }
37}
38
39#[derive(Clone, PartialEq, Eq)]
41pub struct ExpressionParseDiagnostic(ExpressionParseError);
42
43impl ExpressionParseDiagnostic {
44 pub fn new(error: ExpressionParseError) -> Self {
46 Self(error)
47 }
48}
49
50impl fmt::Debug for ExpressionParseDiagnostic {
51 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
52 fmt::Debug::fmt(&self.0, f)
53 }
54}
55
56impl fmt::Display for ExpressionParseDiagnostic {
57 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
58 fmt::Display::fmt(&self.0, f)
59 }
60}
61
62impl StdError for ExpressionParseDiagnostic {
63 fn source(&self) -> Option<&(dyn StdError + 'static)> {
64 self.0.source()
65 }
66}
67
68impl Diagnostic for ExpressionParseDiagnostic {
69 fn source_code(&self) -> Option<&dyn SourceCode> {
70 Some(&self.0.input)
71 }
72
73 fn labels(&self) -> Option<Box<dyn Iterator<Item = LabeledSpan> + '_>> {
74 let label = LabeledSpan::new_with_span(Some(self.0.kind.to_string()), self.0.span.clone());
75 Some(Box::new(std::iter::once(label)))
76 }
77}
78
79impl IntoMietteDiagnostic for ExpressionParseError {
80 type IntoDiagnostic = ExpressionParseDiagnostic;
81
82 fn into_diagnostic(self) -> Self::IntoDiagnostic {
83 ExpressionParseDiagnostic::new(self)
84 }
85}
86
87#[derive(Clone, PartialEq, Eq)]
89pub struct TripleParseDiagnostic {
90 error: TripleParseError,
91 triple_str: String,
93}
94
95impl TripleParseDiagnostic {
96 pub fn new(error: TripleParseError) -> Self {
98 let triple_str = error.triple_str().to_owned();
99 Self { error, triple_str }
100 }
101}
102
103impl fmt::Debug for TripleParseDiagnostic {
104 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
105 fmt::Debug::fmt(&self.error, f)
106 }
107}
108
109impl fmt::Display for TripleParseDiagnostic {
110 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
111 fmt::Display::fmt(&self.error, f)
112 }
113}
114
115impl StdError for TripleParseDiagnostic {
116 fn source(&self) -> Option<&(dyn StdError + 'static)> {
117 self.error.source()
118 }
119}
120
121impl Diagnostic for TripleParseDiagnostic {
122 fn source_code(&self) -> Option<&dyn SourceCode> {
123 Some(&self.triple_str as &dyn SourceCode)
124 }
125
126 fn labels(&self) -> Option<Box<dyn Iterator<Item = LabeledSpan> + '_>> {
127 let label = LabeledSpan::new_with_span(
128 Some(
129 self.error
130 .source()
131 .expect("TripleParseError always returns a source")
132 .to_string(),
133 ),
134 (0, self.triple_str.len()),
135 );
136 Some(Box::new(std::iter::once(label)))
137 }
138}
139
140impl IntoMietteDiagnostic for TripleParseError {
141 type IntoDiagnostic = TripleParseDiagnostic;
142
143 fn into_diagnostic(self) -> Self::IntoDiagnostic {
144 TripleParseDiagnostic::new(self)
145 }
146}
147
148#[derive(Clone, PartialEq, Eq)]
150pub struct PlainStringParseDiagnostic {
151 error: PlainStringParseError,
152 input: String,
154}
155
156impl PlainStringParseDiagnostic {
157 pub fn new(error: PlainStringParseError) -> Self {
159 let input = error.input.clone();
160 Self { error, input }
161 }
162}
163
164impl fmt::Debug for PlainStringParseDiagnostic {
165 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
166 fmt::Debug::fmt(&self.error, f)
167 }
168}
169
170impl fmt::Display for PlainStringParseDiagnostic {
171 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
172 f.write_str("invalid triple identifier")
175 }
176}
177
178impl StdError for PlainStringParseDiagnostic {
179 fn source(&self) -> Option<&(dyn StdError + 'static)> {
180 self.error.source()
181 }
182}
183
184impl Diagnostic for PlainStringParseDiagnostic {
185 fn source_code(&self) -> Option<&dyn SourceCode> {
186 Some(&self.input as &dyn SourceCode)
187 }
188
189 fn labels(&self) -> Option<Box<dyn Iterator<Item = LabeledSpan> + '_>> {
190 let label = LabeledSpan::new_with_span(
191 Some("character must be alphanumeric, -, _ or .".to_owned()),
192 self.error.span(),
193 );
194 Some(Box::new(std::iter::once(label)))
195 }
196}
197
198impl IntoMietteDiagnostic for PlainStringParseError {
199 type IntoDiagnostic = PlainStringParseDiagnostic;
200
201 fn into_diagnostic(self) -> Self::IntoDiagnostic {
202 PlainStringParseDiagnostic::new(self)
203 }
204}
205
206#[derive(Clone, Debug)]
209pub struct RustcVersionVerboseParseDiagnostic(RustcVersionVerboseParseError);
210
211impl RustcVersionVerboseParseDiagnostic {
212 pub fn new(error: RustcVersionVerboseParseError) -> Self {
214 Self(error)
215 }
216}
217
218impl fmt::Display for RustcVersionVerboseParseDiagnostic {
219 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
220 match &self.0 {
221 RustcVersionVerboseParseError::MissingHostLine { .. } => {
226 f.write_str("output from `rustc -vV` did not contain a `host:` line")
227 }
228 RustcVersionVerboseParseError::InvalidUtf8(_) => fmt::Display::fmt(&self.0, f),
231 _ => fmt::Display::fmt(&self.0, f),
232 }
233 }
234}
235
236impl StdError for RustcVersionVerboseParseDiagnostic {
237 fn source(&self) -> Option<&(dyn StdError + 'static)> {
238 self.0.source()
239 }
240}
241
242impl Diagnostic for RustcVersionVerboseParseDiagnostic {
243 fn source_code(&self) -> Option<&dyn SourceCode> {
244 match &self.0 {
245 RustcVersionVerboseParseError::MissingHostLine { output } => {
246 Some(output as &dyn SourceCode)
247 }
248 RustcVersionVerboseParseError::InvalidUtf8(_) => None,
249 _ => None,
250 }
251 }
252
253 fn labels(&self) -> Option<Box<dyn Iterator<Item = LabeledSpan> + '_>> {
254 match &self.0 {
255 RustcVersionVerboseParseError::MissingHostLine { output } => {
256 let label = LabeledSpan::new_with_span(
257 Some("expected a `host: <triple>` line in this output".to_owned()),
258 (0, output.len()),
259 );
260 Some(Box::new(std::iter::once(label)))
261 }
262 RustcVersionVerboseParseError::InvalidUtf8(_) => None,
263 _ => None,
264 }
265 }
266}
267
268impl IntoMietteDiagnostic for RustcVersionVerboseParseError {
269 type IntoDiagnostic = RustcVersionVerboseParseDiagnostic;
270
271 fn into_diagnostic(self) -> Self::IntoDiagnostic {
272 RustcVersionVerboseParseDiagnostic::new(self)
273 }
274}
275
276impl IntoMietteDiagnostic for CustomTripleCreateError {
277 type IntoDiagnostic = CustomTripleCreateDiagnostic;
278
279 fn into_diagnostic(self) -> Self::IntoDiagnostic {
280 CustomTripleCreateDiagnostic::new(self)
281 }
282}
283
284pub struct CustomTripleCreateDiagnostic(CustomTripleCreateError);
286
287impl CustomTripleCreateDiagnostic {
288 pub fn new(error: CustomTripleCreateError) -> Self {
290 Self(error)
291 }
292}
293
294impl fmt::Debug for CustomTripleCreateDiagnostic {
295 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
296 fmt::Debug::fmt(&self.0, f)
297 }
298}
299
300impl fmt::Display for CustomTripleCreateDiagnostic {
301 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
302 fmt::Display::fmt(&self.0, f)
303 }
304}
305
306impl StdError for CustomTripleCreateDiagnostic {
307 fn source(&self) -> Option<&(dyn StdError + 'static)> {
308 if self.0.input().is_some() && self.0.line_and_column().is_some() {
310 None
311 } else {
312 self.0.source()
313 }
314 }
315}
316
317impl Diagnostic for CustomTripleCreateDiagnostic {
318 fn source_code(&self) -> Option<&dyn SourceCode> {
319 self.0.input_string().map(|input| input as &dyn SourceCode)
320 }
321
322 fn labels(&self) -> Option<Box<dyn Iterator<Item = LabeledSpan> + '_>> {
323 let input = self.0.input()?;
326 let (line, column) = self.0.line_and_column()?;
327
328 let source_offset = SourceOffset::from_location(input, line, column);
329 let span = SourceSpan::new(source_offset, 0);
332
333 let label = LabeledSpan::new_with_span(self.0.label(), span);
334 Some(Box::new(std::iter::once(label)))
335 }
336}