1use std::fmt;
2use std::fmt::Display;
3
4#[derive(Debug, Clone, PartialOrd, PartialEq)]
6pub enum ParseError<'a, I> {
7 Mismatch {
9 input: &'a [I],
10 offset: usize,
11 length: usize,
12 message: String,
13 },
14 Conversion {
16 input: &'a [I],
17 offset: usize,
18 length: usize,
19 message: String,
20 },
21 Incomplete,
23 Expect {
25 offset: usize,
26 inner: Box<ParseError<'a, I>>,
27 message: String,
28 },
29 Custom {
31 offset: usize,
32 inner: Option<Box<ParseError<'a, I>>>,
33 message: String,
34 },
35}
36
37impl<'a, I> Display for ParseError<'a, I> {
38 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
39 match self {
40 ParseError::Incomplete => write!(f, "Incomplete"),
41 ParseError::Mismatch {
42 ref message,
43 ref offset,
44 ..
45 } => write!(f, "Mismatch at {}: {}", offset, message),
46 ParseError::Conversion {
47 ref message,
48 ref offset,
49 ..
50 } => write!(f, "Conversion failed at {}: {}", offset, message),
51 ParseError::Expect {
52 ref message,
53 ref offset,
54 ref inner,
55 } => write!(f, "{} at {}: {}", message, offset, inner),
56 ParseError::Custom {
57 ref message,
58 ref offset,
59 inner: Some(ref inner),
60 } => write!(f, "{} at {}, (inner: {})", message, offset, inner),
61 ParseError::Custom {
62 ref message,
63 ref offset,
64 inner: None,
65 } => write!(f, "{} at {}", message, offset),
66 }
67 }
68}
69
70impl<'a> ParseError<'a, char> {
71 pub fn input_string(&self) -> Option<String> {
72 self.input().map(|chars| String::from_iter(chars))
73 }
74}
75
76impl<'a> ParseError<'a, u8> {
77 pub fn input_string(&self) -> Option<String> {
78 match self.input() {
79 Some(bytes) => match std::str::from_utf8(bytes) {
80 Ok(s) => Some(s.to_string()),
81 Err(_) => Some("".to_string()),
82 },
83 None => None,
84 }
85 }
86}
87
88impl<'a, I> ParseError<'a, I> {
89 pub fn input(&self) -> Option<&'a [I]> {
90 match self {
91 ParseError::Incomplete => None,
92 ParseError::Mismatch {
93 input, offset, length, ..
94 } => Some(&input[*offset..(*offset + length)]),
95 ParseError::Conversion {
96 input, offset, length, ..
97 } => Some(&input[*offset..(*offset + length)]),
98 ParseError::Expect { ref inner, .. } => inner.input(),
99 ParseError::Custom {
100 inner: Some(ref inner), ..
101 } => inner.input(),
102 ParseError::Custom { inner: None, .. } => None,
103 }
104 }
105
106 pub fn is_expect(&self) -> bool {
107 match self {
108 ParseError::Expect { .. } => true,
109 _ => false,
110 }
111 }
112
113 pub fn is_custom(&self) -> bool {
114 match self {
115 ParseError::Custom { .. } => true,
116 _ => false,
117 }
118 }
119
120 pub fn is_mismatch(&self) -> bool {
121 match self {
122 ParseError::Mismatch { .. } => true,
123 _ => false,
124 }
125 }
126
127 pub fn is_conversion(&self) -> bool {
128 match self {
129 ParseError::Conversion { .. } => true,
130 _ => false,
131 }
132 }
133
134 pub fn is_in_complete(&self) -> bool {
135 match self {
136 ParseError::Incomplete => true,
137 _ => false,
138 }
139 }
140
141 pub fn of_expect(offset: usize, inner: Box<ParseError<'a, I>>, message: String) -> Self {
142 ParseError::Expect { offset, inner, message }
143 }
144
145 pub fn of_custom(offset: usize, inner: Option<Box<ParseError<'a, I>>>, message: String) -> Self {
146 ParseError::Custom { offset, inner, message }
147 }
148
149 pub fn of_mismatch(input: &'a [I], offset: usize, length: usize, message: String) -> Self {
150 ParseError::Mismatch {
151 input,
152 offset,
153 length,
154 message,
155 }
156 }
157
158 pub fn of_conversion(input: &'a [I], offset: usize, length: usize, message: String) -> Self {
159 ParseError::Conversion {
160 input,
161 offset,
162 length,
163 message,
164 }
165 }
166
167 pub fn of_in_complete() -> Self {
168 ParseError::Incomplete
169 }
170}