1use crate::entry::Entry;
2use crate::tokenizer::SpannedToken;
3use crate::{Event, Item, Token};
4use logos::Span;
5use miette::{Diagnostic, SourceSpan};
6use std::error::Error;
7use std::fmt::{Display, Formatter};
8use thiserror::Error;
9
10#[derive(Error, Debug, Clone, Diagnostic)]
12pub enum VdfError {
13 #[error(transparent)]
14 #[diagnostic(transparent)]
15 UnexpectedToken(#[from] UnexpectedTokenError),
17 #[error(transparent)]
18 #[diagnostic(transparent)]
19 NoValidToken(#[from] NoValidTokenError),
21 #[error(transparent)]
22 #[diagnostic(transparent)]
23 WrongEventType(Box<WrongEventTypeError>),
25 #[error(transparent)]
26 #[diagnostic(transparent)]
27 ParseEntry(#[from] ParseEntryError),
29 #[error(transparent)]
30 #[diagnostic(transparent)]
31 ParseItem(#[from] ParseItemError),
33 #[error(transparent)]
34 #[diagnostic(transparent)]
35 ParseString(#[from] ParseStringError),
37 #[error(transparent)]
38 #[diagnostic(transparent)]
39 UnknownVariant(#[from] UnknownVariantError),
41 #[error(transparent)]
42 #[diagnostic(transparent)]
43 SerdeParse(#[from] SerdeParseError),
45 #[error(transparent)]
46 #[diagnostic(transparent)]
47 Other(#[from] UnknownError),
48}
49
50impl From<WrongEventTypeError> for VdfError {
51 fn from(value: WrongEventTypeError) -> Self {
52 Self::WrongEventType(value.into())
53 }
54}
55
56impl VdfError {
57 pub fn source(&self) -> Option<&str> {
58 let src = match self {
59 VdfError::Other(e) => e.src.as_str(),
60 VdfError::UnexpectedToken(e) => e.src.as_str(),
61 VdfError::NoValidToken(e) => e.src.as_str(),
62 VdfError::WrongEventType(e) => e.src.as_str(),
63 VdfError::SerdeParse(e) => e.src.as_str(),
64 VdfError::UnknownVariant(e) => e.src.as_str(),
65 _ => {
66 return None;
67 }
68 };
69 (!src.is_empty()).then_some(src)
70 }
71 pub fn span(&self) -> Option<SourceSpan> {
72 let span = match self {
73 VdfError::Other(e) => e.err_span,
74 VdfError::UnexpectedToken(e) => e.err_span,
75 VdfError::NoValidToken(e) => e.err_span,
76 VdfError::WrongEventType(e) => e.err_span,
77 VdfError::SerdeParse(e) => e.err_span,
78 VdfError::UnknownVariant(e) => e.err_span,
79 _ => {
80 return None;
81 }
82 };
83 (!span.is_empty()).then_some(span)
84 }
85
86 pub(crate) fn with_source_span_if_none<Sp: Into<SourceSpan>, Sr: Into<String>>(
87 self,
88 span: Sp,
89 source: Sr,
90 ) -> VdfError {
91 if self.source().is_none() {
92 self.with_source_span(span, source)
93 } else {
94 self
95 }
96 }
97 pub(crate) fn with_source_span<Sp: Into<SourceSpan>, Sr: Into<String>>(
98 self,
99 span: Sp,
100 source: Sr,
101 ) -> VdfError {
102 match self {
103 VdfError::Other(e) => UnknownError {
104 src: source.into(),
105 err_span: span.into(),
106 ..e
107 }
108 .into(),
109 VdfError::UnexpectedToken(e) => UnexpectedTokenError {
110 src: source.into(),
111 err_span: span.into(),
112 ..e
113 }
114 .into(),
115 VdfError::NoValidToken(e) => NoValidTokenError {
116 src: source.into(),
117 err_span: span.into(),
118 ..e
119 }
120 .into(),
121 VdfError::WrongEventType(e) => WrongEventTypeError {
122 src: source.into(),
123 err_span: span.into(),
124 ..*e
125 }
126 .into(),
127 VdfError::SerdeParse(e) => SerdeParseError {
128 src: source.into(),
129 err_span: span.into(),
130 ..e
131 }
132 .into(),
133 VdfError::UnknownVariant(e) => UnknownVariantError {
134 src: source.into(),
135 err_span: span.into(),
136 ..e
137 }
138 .into(),
139 _ => self,
140 }
141 }
142}
143
144struct CommaSeperated<'a, T>(&'a [T]);
145
146impl<T: Display> Display for CommaSeperated<'_, T> {
147 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
148 let mut tokens = self.0.iter();
149 if let Some(token) = tokens.next() {
150 write!(f, "{}", token)?;
151 } else {
152 return Ok(());
153 }
154
155 for token in tokens {
156 write!(f, ", {}", token)?;
157 }
158
159 Ok(())
160 }
161}
162
163#[derive(Debug, Clone, Diagnostic, Error)]
164#[diagnostic(code(vmt_reader::unexpected_token))]
165#[error("{error}")]
166pub struct UnknownError {
167 pub error: String,
168 #[label("{error}")]
169 err_span: SourceSpan,
170 #[source_code]
171 src: String,
172}
173
174impl From<&str> for UnknownError {
175 fn from(value: &str) -> Self {
176 UnknownError {
177 error: value.to_string(),
178 err_span: (0..0).into(),
179 src: String::new(),
180 }
181 }
182}
183
184impl From<String> for UnknownError {
185 fn from(value: String) -> Self {
186 UnknownError {
187 error: value,
188 err_span: (0..0).into(),
189 src: String::new(),
190 }
191 }
192}
193
194#[derive(Debug, Clone, Diagnostic)]
196#[diagnostic(code(vmt_reader::unexpected_token))]
197pub struct UnexpectedTokenError {
198 #[label("Expected {}", CommaSeperated(self.expected))]
199 err_span: SourceSpan,
200 pub expected: &'static [Token],
201 pub found: Option<Token>,
202 #[source_code]
203 src: String,
204}
205
206impl UnexpectedTokenError {
207 pub fn new(
208 expected: &'static [Token],
209 found: Option<Token>,
210 err_span: SourceSpan,
211 src: String,
212 ) -> Self {
213 UnexpectedTokenError {
214 err_span,
215 expected,
216 found,
217 src,
218 }
219 }
220}
221
222impl Display for UnexpectedTokenError {
223 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
224 match &self.found {
225 Some(token) => write!(
226 f,
227 "Unexpected token, found {} expected one of {}",
228 token,
229 CommaSeperated(self.expected)
230 ),
231 None => write!(
232 f,
233 "Unexpected end of input expected one of {}",
234 CommaSeperated(self.expected)
235 ),
236 }
237 }
238}
239
240impl Error for UnexpectedTokenError {}
241
242#[derive(Debug, Clone, Diagnostic, Error)]
244#[diagnostic(code(vmt_reader::no_valid_token))]
245#[error("No valid token found, expected one of {}", CommaSeperated(self.expected))]
246pub struct NoValidTokenError {
247 #[label("Expected {}", CommaSeperated(self.expected))]
248 err_span: SourceSpan,
249 pub expected: &'static [Token],
250 #[source_code]
251 src: String,
252}
253
254impl NoValidTokenError {
255 pub fn new(expected: &'static [Token], err_span: SourceSpan, src: String) -> Self {
256 NoValidTokenError {
257 err_span,
258 expected,
259 src,
260 }
261 }
262}
263
264#[derive(Debug, Clone, Diagnostic, Error)]
266#[diagnostic(code(vmt_reader::wrong_value_type))]
267#[error("Wrong event to for conversion, expected a {expected} but found a {got}")]
268pub struct WrongEventTypeError {
269 pub expected: &'static str,
270 pub got: &'static str,
271 pub event: Event<'static>,
272 #[label("Expected a {}", self.expected)]
273 err_span: SourceSpan,
274 #[source_code]
275 src: String,
276}
277
278impl WrongEventTypeError {
279 pub fn new(event: Event, expected: &'static str, got: &'static str) -> Self {
280 WrongEventTypeError {
281 err_span: event.span().into(),
282 event: event.into_owned(),
283 expected,
284 got,
285 src: String::new(),
286 }
287 }
288 pub fn new_with_source(
289 event: Event,
290 expected: &'static str,
291 got: &'static str,
292 src: String,
293 ) -> Self {
294 WrongEventTypeError {
295 err_span: event.span().into(),
296 event: event.into_owned(),
297 expected,
298 got,
299 src,
300 }
301 }
302
303 pub fn with_source(self, src: String) -> Self {
304 WrongEventTypeError { src, ..self }
305 }
306}
307
308#[derive(Debug, Clone, Error, Diagnostic)]
309#[error("Can't parse entry {value:?} as {ty}")]
310#[diagnostic(code(vmt_parser::parse_value))]
311pub struct ParseEntryError {
312 pub ty: &'static str,
313 pub value: Entry,
314}
315
316impl ParseEntryError {
317 pub fn new(ty: &'static str, value: Entry) -> Self {
318 ParseEntryError { ty, value }
319 }
320}
321
322#[derive(Debug, Clone, Error, Diagnostic)]
323#[error("Can't parse entry {value:?} as {ty}")]
324#[diagnostic(code(vmt_parser::parse_item))]
325pub struct ParseItemError {
326 pub ty: &'static str,
327 pub value: Item<'static>,
328}
329
330impl ParseItemError {
331 pub fn new(ty: &'static str, value: Item) -> Self {
332 ParseItemError {
333 ty,
334 value: value.into_owned(),
335 }
336 }
337}
338
339#[derive(Debug, Clone, Error, Diagnostic)]
340#[error("Can't parse string {value:?} as {ty}")]
341#[diagnostic(code(vmt_parser::parse_string))]
342pub struct ParseStringError {
343 pub ty: &'static str,
344 pub value: String,
345}
346
347impl ParseStringError {
348 pub fn new(ty: &'static str, value: &str) -> Self {
349 ParseStringError {
350 ty,
351 value: value.into(),
352 }
353 }
354}
355
356#[derive(Debug, Clone, Error, Diagnostic)]
357#[error("Can't parse {value:?} as {ty}")]
358#[diagnostic(code(vmt_parser::parse_serde))]
359pub struct SerdeParseError {
360 pub ty: &'static str,
361 pub value: String,
362 #[label("Expected a {ty}")]
363 err_span: SourceSpan,
364 #[source_code]
365 src: String,
366}
367
368impl SerdeParseError {
369 pub fn new(ty: &'static str, value: &str, span: Span, src: &str) -> Self {
370 SerdeParseError {
371 ty,
372 value: value.into(),
373 err_span: span.into(),
374 src: src.into(),
375 }
376 }
377}
378
379#[derive(Debug, Clone, Error, Diagnostic)]
380#[error("Unknown variant {variant:?} expected on of {}", ExpectedVariants(self.expected))]
381#[diagnostic(code(vmt_parser::unknown_variant))]
382pub struct UnknownVariantError {
383 variant: String,
384 expected: &'static [&'static str],
385 #[label("{}", ExpectedVariants(self.expected))]
386 err_span: SourceSpan,
387 #[source_code]
388 src: String,
389}
390
391struct ExpectedVariants(&'static [&'static str]);
392
393impl Display for ExpectedVariants {
394 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
395 if self.0.is_empty() {
396 write!(f, "there are no variants")
397 } else {
398 write!(f, "expected on of {}", CommaSeperated(self.0))
399 }
400 }
401}
402
403impl UnknownVariantError {
404 pub fn new(variant: &str, expected: &'static [&'static str], span: Span, src: &str) -> Self {
405 UnknownVariantError {
406 variant: variant.into(),
407 expected,
408 err_span: span.into(),
409 src: src.into(),
410 }
411 }
412}
413
414pub trait ExpectToken<'source> {
415 fn expect_token(
416 self,
417 expected: &'static [Token],
418 source: &'source str,
419 ) -> Result<SpannedToken, VdfError>;
420}
421
422impl<'source, T: ExpectToken<'source>> ExpectToken<'source> for Option<T> {
423 fn expect_token(
424 self,
425 expected: &'static [Token],
426 source: &'source str,
427 ) -> Result<SpannedToken, VdfError> {
428 self.ok_or_else(|| {
429 NoValidTokenError::new(expected, (source.len()..source.len()).into(), source.into())
430 .into()
431 })
432 .and_then(|token| token.expect_token(expected, source))
433 }
434}
435
436impl<'source> ExpectToken<'source> for Result<SpannedToken, Span> {
437 fn expect_token(
438 self,
439 expected: &'static [Token],
440 source: &'source str,
441 ) -> Result<SpannedToken, VdfError> {
442 self.map_err(|span| NoValidTokenError::new(expected, span.into(), source.into()).into())
443 .and_then(|token| token.expect_token(expected, source))
444 }
445}
446
447impl<'source> ExpectToken<'source> for SpannedToken {
448 fn expect_token(
449 self,
450 expected: &'static [Token],
451 source: &'source str,
452 ) -> Result<SpannedToken, VdfError> {
453 if expected.iter().any(|expect| self.token.eq(expect)) {
454 Ok(self)
455 } else {
456 Err(UnexpectedTokenError::new(
457 expected,
458 Some(self.token),
459 self.span.into(),
460 source.into(),
461 )
462 .into())
463 }
464 }
465}
466
467impl serde::de::Error for VdfError {
468 fn custom<T>(msg: T) -> Self
469 where
470 T: Display,
471 {
472 VdfError::Other(UnknownError {
473 err_span: (0..0).into(),
474 src: String::new(),
475 error: msg.to_string(),
476 })
477 }
478
479 fn unknown_variant(variant: &str, expected: &'static [&'static str]) -> Self {
480 UnknownVariantError::new(variant, expected, 0..0, "").into()
481 }
482}
483
484pub(crate) trait ResultExt {
485 fn ensure_span(self, span: Span, source: &str) -> Self;
486}
487
488impl<T> ResultExt for Result<T, VdfError> {
489 fn ensure_span(self, span: Span, source: &str) -> Self {
490 self.map_err(|e| e.with_source_span_if_none(span, source))
491 }
492}