1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170
use std::fmt; use std::error; use nom::{Err, Needed}; #[derive(PartialEq, Debug, Clone)] pub enum Error { ParseError(String), ParseIncomplete(String), GenerateError(String), RecursionLimit(String), } impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { Error::ParseError(ref s) => write!(f, "{}", s), Error::ParseIncomplete(ref s) => write!(f, "{}", s), Error::GenerateError(ref s) => write!(f, "{}", s), Error::RecursionLimit(ref s) => write!(f, "{}", s), } } } impl error::Error for Error { fn description(&self) -> &str { "BNF error" } } impl<'a> From<Err<&'a [u8]>> for Error { fn from(err: Err<&[u8]>) -> Self { let string = match err { Err::Code(_) => String::from("Parsing error: Unknown origin"), Err::Node(_, n) => { n.iter().fold( String::from("Parsing error: Unknown origin."), |s, e| s + &format!(" {}", e), ) } Err::Position(_, p) => { format!( "Parsing error: When input is {}", String::from_utf8_lossy(p) ) } Err::NodePosition(_, p, n) => { n.iter().fold( format!( "Parsing error: When input is {}.", String::from_utf8_lossy(p) ), |s, e| s + &format!(" {}", e), ) } }; Error::ParseError(string) } } impl From<Needed> for Error { fn from(needed: Needed) -> Self { let string = match needed { Needed::Unknown => format!("Data error: insufficient size, expectation unknown"), Needed::Size(s) => format!("Data error: insufficient size, expected {} bytes", s), }; Error::ParseIncomplete(string) } } #[cfg(test)] mod tests { use nom::IResult; use error::Error; named!( give_error_kind, do_parse!( tag!("1234") >> res: tag!("5678") >> (res) ) ); #[test] fn gets_error_error() { let nom_result = give_error_kind("12340".as_bytes()); let nom_error; match nom_result { IResult::Error(e) => nom_error = e, _ => panic!("gets_error_error should result in IResult::Error"), } let bnf_error: Result<String, Error> = Err(Error::from(nom_error)); assert!( bnf_error.is_err(), "production result should be error {:?}", bnf_error ); match bnf_error.unwrap_err() { Error::ParseError(_) => (), e => panic!("production error should be error parsing: {:?}", e), } } #[test] fn gets_error_incomplete() { let nom_result = give_error_kind("".as_bytes()); let nom_error; match nom_result { IResult::Incomplete(e) => nom_error = e, _ => panic!("gets_error_error should result in IResult::Error"), } let bnf_error: Result<String, Error> = Err(Error::from(nom_error)); assert!( bnf_error.is_err(), "production result should be error {:?}", bnf_error ); match bnf_error.unwrap_err() { Error::ParseIncomplete(_) => (), e => panic!("production error should be incomplete: {:?}", e), } } #[test] fn uses_error_recursion_limit() { let bnf_error = Error::RecursionLimit(String::from("reucrsion limit reached!")); match bnf_error { Error::RecursionLimit(_) => (), e => panic!("should match on reursion limit: {:?}", e), } } #[test] fn uses_error_generate() { let bnf_error = Error::GenerateError(String::from("error generating!")); match bnf_error { Error::GenerateError(_) => (), e => panic!("should match on generate error: {:?}", e), } } #[test] fn test_error_display() { let parse_error = Error::ParseError(String::from("syntax error!")); let incomplete_error = Error::ParseIncomplete(String::from("incomplete data size!")); let generate_error = Error::GenerateError(String::from("error generating!")); let recursion_error = Error::RecursionLimit(String::from("recursion limit reached!")); assert_eq!(parse_error.to_string(), String::from("syntax error!")); assert_eq!( incomplete_error.to_string(), String::from("incomplete data size!") ); assert_eq!( generate_error.to_string(), String::from("error generating!") ); assert_eq!( recursion_error.to_string(), String::from("recursion limit reached!") ); } }