Skip to main content

bnf/
error.rs

1use std::error;
2use std::fmt;
3use std::str;
4
5use nom::{Err, error::ErrorKind};
6
7#[derive(PartialEq, Eq, Debug, Clone)]
8#[non_exhaustive]
9pub enum Error {
10    ParseError(String),
11    GenerateError(String),
12    ValidationError(String),
13}
14
15impl fmt::Display for Error {
16    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
17        match self {
18            Error::ParseError(s) | Error::GenerateError(s) | Error::ValidationError(s) => {
19                write!(f, "{s}")
20            }
21        }
22    }
23}
24
25impl error::Error for Error {}
26
27impl From<nom::error::Error<&str>> for Error {
28    fn from(err: nom::error::Error<&str>) -> Self {
29        Error::ParseError(format!("Parsing error: {err:?}"))
30    }
31}
32
33impl From<Err<nom::error::Error<&str>>> for Error {
34    fn from(err: Err<nom::error::Error<&str>>) -> Self {
35        Error::ParseError(format!("Parsing error: {err:?}"))
36    }
37}
38
39impl From<(&'_ str, ErrorKind)> for Error {
40    fn from(err: (&str, ErrorKind)) -> Self {
41        let string = format!("Parsing error: {:?}\n {:?}", err.1, err.0);
42        Error::ParseError(string)
43    }
44}
45
46#[cfg(test)]
47mod tests {
48    use crate::error::Error;
49    use nom::{Err, IResult, bytes::complete::tag};
50
51    fn give_error_kind(input: &str) -> IResult<&str, &str> {
52        let (input, _) = tag("1234")(input)?;
53        let (input, res) = tag("5678")(input)?;
54        Ok((input, res))
55    }
56
57    #[test]
58    fn gets_error_error() {
59        let nom_result = give_error_kind("12340");
60        assert!(matches!(nom_result, Err(Err::Error(_))));
61    }
62
63    #[test]
64    fn gets_error_on_incomplete() {
65        let nom_result = give_error_kind("").map_err(Error::from);
66        assert!(matches!(nom_result, Err(Error::ParseError(_))));
67    }
68
69    #[test]
70    fn uses_error_generate() {
71        let bnf_error = Error::GenerateError(String::from("error generating!"));
72        assert!(matches!(bnf_error, Error::GenerateError(_)));
73    }
74
75    #[test]
76    fn test_error_display() {
77        let parse_error = Error::ParseError(String::from("parsing error!"));
78        let generate_error = Error::GenerateError(String::from("error generating!"));
79        let validation_error = Error::ValidationError(String::from("validation error!"));
80
81        assert_eq!(parse_error.to_string(), String::from("parsing error!"));
82        assert_eq!(
83            generate_error.to_string(),
84            String::from("error generating!")
85        );
86        assert_eq!(
87            validation_error.to_string(),
88            String::from("validation error!")
89        );
90    }
91
92    #[test]
93    fn from_nom_verbose_error() {
94        let error = nom::error::Error::new("test", nom::error::ErrorKind::Tag);
95        assert!(matches!(Error::from(error), Error::ParseError(_)));
96    }
97
98    #[test]
99    fn from_str_and_nom_verbose_error_kind() {
100        let description = "anything";
101        let error_kind = nom::error::ErrorKind::Char;
102        assert!(matches!(
103            Error::from((description, error_kind)),
104            Error::ParseError(_)
105        ));
106    }
107
108    #[test]
109    fn clone_error() {
110        let error = Error::ParseError(String::from("parsing error!"));
111        let clone = error.clone();
112        assert_eq!(error, clone);
113    }
114
115    #[test]
116    fn from_nom_err_failure() {
117        let error = nom::error::Error::new("test", nom::error::ErrorKind::Tag);
118        let err = Err::Failure(error);
119        let bnf_error = Error::from(err);
120        assert!(matches!(bnf_error, Error::ParseError(_)));
121        assert!(bnf_error.to_string().contains("Parsing error:"));
122    }
123
124    #[test]
125    fn from_nom_err_incomplete() {
126        let err = Err::Incomplete(nom::Needed::Unknown);
127        let bnf_error = Error::from(err);
128        assert!(matches!(bnf_error, Error::ParseError(_)));
129        assert!(bnf_error.to_string().contains("Parsing error:"));
130    }
131
132    #[test]
133    fn error_trait_impl() {
134        // Test that Error implements std::error::Error
135        let error = Error::ParseError(String::from("test"));
136        let error_ref: &dyn std::error::Error = &error;
137        assert_eq!(error_ref.to_string(), "test");
138    }
139}