sqlparser_mysql/base/
error.rs

1use std::fmt;
2
3use nom::error::{ContextError, ErrorKind, FromExternalError, ParseError};
4use nom::InputLength;
5
6/// [nom::branch::alt] return the last error of the branch by default
7///
8/// With a custom error type it is possible to have
9/// [nom::branch::alt] return the error of the parser
10/// that went the farthest in the input data.
11///
12/// There is little difference between [ParseSQLError] and [nom::error::VerboseError]
13#[derive(Clone, Debug, PartialEq)]
14pub struct ParseSQLError<I>
15where
16    I: InputLength,
17{
18    pub errors: Vec<(I, ParseSQLErrorKind)>,
19}
20
21#[derive(Clone, Debug, PartialEq)]
22/// Error context for `ParseSQLError`
23pub enum ParseSQLErrorKind {
24    /// Static string added by the `context` function
25    Context(&'static str),
26    /// Indicates which character was expected by the `char` function
27    Char(char),
28    /// Error kind given by various nom parsers
29    Nom(ErrorKind),
30}
31
32impl<I> ParseError<I> for ParseSQLError<I>
33where
34    I: InputLength,
35{
36    fn from_error_kind(input: I, kind: ErrorKind) -> Self {
37        ParseSQLError {
38            errors: vec![(input, ParseSQLErrorKind::Nom(kind))],
39        }
40    }
41
42    fn append(input: I, kind: ErrorKind, mut other: Self) -> Self {
43        other.errors.push((input, ParseSQLErrorKind::Nom(kind)));
44        other
45    }
46
47    fn from_char(input: I, c: char) -> Self {
48        ParseSQLError {
49            errors: vec![(input, ParseSQLErrorKind::Char(c))],
50        }
51    }
52
53    fn or(self, other: Self) -> Self {
54        if self.errors[0].0.input_len() >= other.errors[0].0.input_len() {
55            other
56        } else {
57            self
58        }
59    }
60}
61
62impl<I: nom::InputLength> ContextError<I> for ParseSQLError<I> {
63    fn add_context(input: I, ctx: &'static str, mut other: Self) -> Self {
64        other.errors.push((input, ParseSQLErrorKind::Context(ctx)));
65        other
66    }
67}
68
69impl<I: InputLength, E> FromExternalError<I, E> for ParseSQLError<I> {
70    /// Create a new error from an input position and an external error
71    fn from_external_error(input: I, kind: ErrorKind, _e: E) -> Self {
72        Self::from_error_kind(input, kind)
73    }
74}
75
76impl<I: fmt::Display + InputLength> fmt::Display for ParseSQLError<I> {
77    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
78        writeln!(f, "Parse error:")?;
79        for (input, error) in &self.errors {
80            match error {
81                ParseSQLErrorKind::Nom(e) => writeln!(f, "{:?} at: {}", e, input)?,
82                ParseSQLErrorKind::Char(c) => writeln!(f, "expected '{}' at: {}", c, input)?,
83                ParseSQLErrorKind::Context(s) => writeln!(f, "in section '{}', at: {}", s, input)?,
84            }
85        }
86
87        Ok(())
88    }
89}
90
91impl<I: fmt::Debug + fmt::Display + InputLength> std::error::Error for ParseSQLError<I> {}