vdf_reader/
error.rs

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/// Any error that occurred while trying to parse the vdf file
11#[derive(Error, Debug, Clone, Diagnostic)]
12pub enum VdfError {
13    #[error(transparent)]
14    #[diagnostic(transparent)]
15    /// A token that wasn't expected was found while parsing
16    UnexpectedToken(#[from] UnexpectedTokenError),
17    #[error(transparent)]
18    #[diagnostic(transparent)]
19    /// No valid token found
20    NoValidToken(#[from] NoValidTokenError),
21    #[error(transparent)]
22    #[diagnostic(transparent)]
23    /// Wrong event to for conversion
24    WrongEventType(Box<WrongEventTypeError>),
25    #[error(transparent)]
26    #[diagnostic(transparent)]
27    /// Failed to parse entry into type
28    ParseEntry(#[from] ParseEntryError),
29    #[error(transparent)]
30    #[diagnostic(transparent)]
31    /// Failed to parse item into type
32    ParseItem(#[from] ParseItemError),
33    #[error(transparent)]
34    #[diagnostic(transparent)]
35    /// Failed to parse string into type
36    ParseString(#[from] ParseStringError),
37    #[error(transparent)]
38    #[diagnostic(transparent)]
39    /// Failed to find an enum variant that matches the found tag
40    UnknownVariant(#[from] UnknownVariantError),
41    #[error(transparent)]
42    #[diagnostic(transparent)]
43    /// Failed to parse serde string
44    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/// A token that wasn't expected was found while parsing
195#[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/// A token that wasn't expected was found while parsing
243#[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/// Wrong event to for conversion
265#[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}