1use std::num::ParseIntError;
3use std::ops::Range;
4
5use codespan_reporting::diagnostic::{Diagnostic, Label};
6use nom::error::{ErrorKind as NomErrorKind, ParseError};
7
8use super::types::Input;
9
10#[derive(Clone, Debug, PartialEq, Eq)]
12pub struct Error {
13 span: Range<usize>,
18
19 kind: ErrorKind,
21}
22
23impl Error {
24 #[must_use]
25 pub(crate) fn new(span: Range<usize>, kind: ErrorKind) -> Self {
26 Self { span, kind }
27 }
28
29 #[must_use]
33 pub fn to_diagnostic(&self) -> Diagnostic<()> {
34 match &self.kind {
35 ErrorKind::Base64AlphabetInvalidLength { length } => Diagnostic::error()
36 .with_message("base64 modifier alphabet must contain exactly 64 characters")
37 .with_labels(vec![Label::primary((), self.span.clone())
38 .with_message(format!("this contains {length} characters"))]),
39
40 ErrorKind::Base64AlphabetIncompatible => Diagnostic::error()
41 .with_message("alphabets used for base64 and base64wide must be identical")
42 .with_labels(vec![Label::primary((), self.span.clone())]),
43
44 ErrorKind::CannotNegateMaskAll => Diagnostic::error()
45 .with_message("negating an unknown byte is not allowed")
46 .with_labels(vec![Label::primary((), self.span.clone())]),
47
48 ErrorKind::ExprTooDeep => Diagnostic::error()
49 .with_message("too many imbricated expressions")
50 .with_labels(vec![Label::primary((), self.span.clone())]),
51
52 ErrorKind::RegexClassRangeInvalid => Diagnostic::error()
53 .with_message("invalid regex class range, start must be <= to end")
54 .with_labels(vec![Label::primary((), self.span.clone())]),
55
56 ErrorKind::RegexNonAsciiByte => Diagnostic::error()
57 .with_message("regex should only contain ascii bytes")
58 .with_labels(vec![Label::primary((), self.span.clone())]),
59
60 ErrorKind::RegexRangeInvalid => Diagnostic::error()
61 .with_message("invalid regex range, start must be <= to end")
62 .with_labels(vec![Label::primary((), self.span.clone())]),
63
64 ErrorKind::RegexTooDeep => Diagnostic::error()
65 .with_message("too many imbricated groups in the regex")
66 .with_labels(vec![Label::primary((), self.span.clone())]),
67
68 ErrorKind::HexStringTooDeep => Diagnostic::error()
69 .with_message("too many imbricated groups in the hex string")
70 .with_labels(vec![Label::primary((), self.span.clone())]),
71
72 ErrorKind::JumpAtBound => Diagnostic::error()
73 .with_message("a list of tokens cannot start or end with a jump")
74 .with_labels(vec![Label::primary((), self.span.clone())]),
75
76 ErrorKind::JumpEmpty => Diagnostic::error()
77 .with_message("jump cannot have a length of 0")
78 .with_labels(vec![Label::primary((), self.span.clone())]),
79
80 ErrorKind::JumpRangeInvalid { from, to } => Diagnostic::error()
81 .with_message(format!("invalid range for the jump: {from} > {to}"))
82 .with_labels(vec![Label::primary((), self.span.clone())]),
83
84 ErrorKind::JumpTooBigInAlternation { limit } => Diagnostic::error()
85 .with_message(format!(
86 "jumps over {limit} not allowed inside alternations (|)",
87 ))
88 .with_labels(vec![Label::primary((), self.span.clone())]),
89
90 ErrorKind::JumpUnboundedInAlternation => Diagnostic::error()
91 .with_message("unbounded jumps not allowed inside alternations (|)")
92 .with_labels(vec![Label::primary((), self.span.clone())]),
93
94 ErrorKind::ModifiersDuplicated { modifier_name } => Diagnostic::error()
95 .with_message(format!(
96 "string modifier {modifier_name} appears multiple times",
97 ))
98 .with_labels(vec![Label::primary((), self.span.clone())]),
99
100 ErrorKind::ModifiersIncompatible {
101 first_modifier_name,
102 second_modifier_name,
103 } => Diagnostic::error()
104 .with_message(format!(
105 "string modifiers {first_modifier_name} and {second_modifier_name} are incompatible",
106 ))
107 .with_labels(vec![Label::primary((), self.span.clone())]),
108
109 ErrorKind::MulOverflow { left, right } => Diagnostic::error()
110 .with_message(format!("multiplication {left} * {right} overflows"))
111 .with_labels(vec![Label::primary((), self.span.clone())]),
112
113 ErrorKind::NomError(_) => Diagnostic::error()
114 .with_message("syntax error")
118 .with_labels(vec![Label::primary((), self.span.clone())]),
119
120 ErrorKind::StrToIntError(err) => Diagnostic::error()
121 .with_message(format!("error converting to integer: {err}"))
122 .with_labels(vec![Label::primary((), self.span.clone())]),
123
124 ErrorKind::StrToHexIntError(err) => Diagnostic::error()
125 .with_message(format!(
126 "error converting hexadecimal notation to integer: {err}"
127 ))
128 .with_labels(vec![Label::primary((), self.span.clone())]),
129
130 ErrorKind::StrToOctIntError(err) => Diagnostic::error()
131 .with_message(format!(
132 "error converting octal notation to integer: {err}"
133 ))
134 .with_labels(vec![Label::primary((), self.span.clone())]),
135
136 ErrorKind::XorRangeInvalidValue { value } => Diagnostic::error()
137 .with_message(format!(
138 "xor range value {value} invalid, must be in [0-255]"
139 ))
140 .with_labels(vec![Label::primary((), self.span.clone())]),
141
142 ErrorKind::XorRangeInvalid { from, to } => Diagnostic::error()
143 .with_message(format!("xor range invalid: {from} > {to}"))
144 .with_labels(vec![Label::primary((), self.span.clone())]),
145 }
146 }
147
148 fn from_nom_error_kind(position: usize, kind: NomErrorKind) -> Self {
149 Self {
150 span: Range {
151 start: position,
152 end: position + 1,
153 },
154 kind: ErrorKind::NomError(kind),
155 }
156 }
157}
158
159impl ParseError<Input<'_>> for Error {
160 fn from_error_kind(input: Input, kind: NomErrorKind) -> Self {
161 Self::from_nom_error_kind(input.get_position_offset(), kind)
162 }
163
164 fn append(_: Input, _: NomErrorKind, other: Self) -> Self {
165 other
166 }
167}
168
169#[derive(Clone, Debug, PartialEq, Eq)]
170pub(crate) enum ErrorKind {
171 Base64AlphabetInvalidLength { length: usize },
175
176 Base64AlphabetIncompatible,
178
179 CannotNegateMaskAll,
181
182 ExprTooDeep,
184
185 HexStringTooDeep,
187
188 JumpAtBound,
190
191 JumpEmpty,
193
194 JumpRangeInvalid { from: u32, to: u32 },
196
197 JumpTooBigInAlternation {
199 limit: u32,
201 },
202
203 JumpUnboundedInAlternation,
205
206 ModifiersDuplicated {
208 modifier_name: String,
210 },
211
212 ModifiersIncompatible {
214 first_modifier_name: String,
216 second_modifier_name: String,
218 },
219
220 MulOverflow { left: i64, right: i64 },
222
223 NomError(NomErrorKind),
225
226 RegexClassRangeInvalid,
228
229 RegexNonAsciiByte,
231
232 RegexRangeInvalid,
234
235 RegexTooDeep,
237
238 StrToIntError(ParseIntError),
240
241 StrToHexIntError(ParseIntError),
243
244 StrToOctIntError(ParseIntError),
246
247 XorRangeInvalidValue { value: i64 },
249
250 XorRangeInvalid { from: u8, to: u8 },
252}
253
254#[cfg(test)]
255mod tests {
256 use super::*;
257 use crate::test_helpers::test_public_type;
258
259 #[test]
260 fn test_public_types() {
261 test_public_type(Error::new(0..3, ErrorKind::JumpEmpty));
262 }
263}