lexical_util/
error.rs

1//! Error type for numeric parsing functions.
2//!
3//! The error type is C-compatible, simplifying use external language
4//! bindings.
5
6#![doc(hidden)]
7
8use core::fmt;
9#[cfg(feature = "std")]
10use std::error;
11
12/// Error code during parsing, indicating failure type.
13#[non_exhaustive]
14#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
15pub enum Error {
16    // PARSE ERRORS
17    /// Integral overflow occurred during numeric parsing.
18    Overflow(usize),
19    /// Integral underflow occurred during numeric parsing.
20    Underflow(usize),
21    /// Invalid digit found before string termination.
22    InvalidDigit(usize),
23    /// Empty byte array found.
24    Empty(usize),
25    /// Empty mantissa found.
26    EmptyMantissa(usize),
27    /// Empty exponent found.
28    EmptyExponent(usize),
29    /// Empty integer found.
30    EmptyInteger(usize),
31    /// Empty fraction found.
32    EmptyFraction(usize),
33    /// Invalid positive mantissa sign was found.
34    InvalidPositiveMantissaSign(usize),
35    /// Mantissa sign was required(usize), but not found.
36    MissingMantissaSign(usize),
37    /// Exponent was present but not allowed.
38    InvalidExponent(usize),
39    /// Invalid positive exponent sign was found.
40    InvalidPositiveExponentSign(usize),
41    /// Exponent sign was required(usize), but not found.
42    MissingExponentSign(usize),
43    /// Exponent was present without fraction component.
44    ExponentWithoutFraction(usize),
45    /// Integer or integer component of float had invalid leading zeros.
46    InvalidLeadingZeros(usize),
47    /// No exponent with required exponent notation.
48    MissingExponent(usize),
49    /// Integral sign was required(usize), but not found.
50    MissingSign(usize),
51    /// Invalid positive sign for an integer was found.
52    InvalidPositiveSign(usize),
53    /// Invalid negative sign for an unsigned type was found.
54    InvalidNegativeSign(usize),
55
56    // NUMBER FORMAT ERRORS
57    /// Invalid radix for the mantissa (significant) digits.
58    InvalidMantissaRadix,
59    /// Invalid base for the exponent.
60    InvalidExponentBase,
61    /// Invalid radix for the exponent digits.
62    InvalidExponentRadix,
63    /// Invalid digit separator character.
64    InvalidDigitSeparator,
65    /// Invalid decimal point character.
66    InvalidDecimalPoint,
67    /// Invalid symbol to represent exponent notation.
68    InvalidExponentSymbol,
69    /// Invalid character for a base prefix.
70    InvalidBasePrefix,
71    /// Invalid character for a base suffix.
72    InvalidBaseSuffix,
73    /// Invalid punctuation characters: multiple symbols overlap.
74    InvalidPunctuation,
75    /// Optional exponent flags were set while disabling exponent notation.
76    InvalidExponentFlags,
77    /// Set no positive mantissa sign while requiring mantissa signs.
78    InvalidMantissaSign,
79    /// Set no positive exponent sign while requiring exponent signs.
80    InvalidExponentSign,
81    /// Set optional special float flags while disable special floats.
82    InvalidSpecial,
83    /// Invalid consecutive integer digit separator.
84    InvalidConsecutiveIntegerDigitSeparator,
85    /// Invalid consecutive fraction digit separator.
86    InvalidConsecutiveFractionDigitSeparator,
87    /// Invalid consecutive exponent digit separator.
88    InvalidConsecutiveExponentDigitSeparator,
89    /// Invalid flags were set without the format feature.
90    InvalidFlags,
91
92    // OPTION ERRORS
93    /// Invalid NaN string: must start with an `n` character.
94    InvalidNanString,
95    /// NaN string is too long.
96    NanStringTooLong,
97    /// Invalid short infinity string: must start with an `i` character.
98    InvalidInfString,
99    /// Short infinity string is too long.
100    InfStringTooLong,
101    /// Invalid long infinity string: must start with an `i` character.
102    InvalidInfinityString,
103    /// Long infinity string is too long.
104    InfinityStringTooLong,
105    /// Long infinity string is too short: it must be as long as short infinity.
106    InfinityStringTooShort,
107    /// Invalid float parsing algorithm.
108    InvalidFloatParseAlgorithm,
109    /// Invalid radix for the significant digits.
110    InvalidRadix,
111    /// Invalid precision flags for writing floats.
112    InvalidFloatPrecision,
113    /// Invalid negative exponent break: break is above 0.
114    InvalidNegativeExponentBreak,
115    /// Invalid positive exponent break: break is below 0.
116    InvalidPositiveExponentBreak,
117
118    // NOT AN ERROR
119    /// An error did not actually occur, and the result was successful.
120    Success,
121}
122
123macro_rules! is_error_type {
124    ($name:ident, $type:ident$($t:tt)*) => (
125        /// const fn check to see if an error is of a specific type.
126        pub const fn $name(&self) -> bool {
127            // Note: enum equality is not a const fn, so use a let expression.
128            if let Self::$type$($t)* = self {
129                true
130            } else {
131                false
132            }
133        }
134    );
135}
136
137impl Error {
138    /// Get a description of the error in a const, panic friendly way.
139    #[inline]
140    pub const fn description(&self) -> &'static str {
141        match self {
142            // PARSE ERRORS
143            Self::Overflow(_) => "'numeric overflow occurred'",
144            Self::Underflow(_) => "'numeric underflow occurred'",
145            Self::InvalidDigit(_) => "'invalid digit found'",
146            Self::Empty(_) => "'the string to parse was empty'",
147            Self::EmptyMantissa(_) => "'no significant digits found'",
148            Self::EmptyExponent(_) => "'exponent notation found without an exponent'",
149            Self::EmptyInteger(_) => "'invalid float with no integer digits'",
150            Self::EmptyFraction(_) => "'invalid float with no fraction digits'",
151            Self::InvalidPositiveMantissaSign(_) => "'invalid `+` sign before significant digits'",
152            Self::MissingMantissaSign(_) => "'missing required `+/-` sign for significant digits'",
153            Self::InvalidExponent(_) => "'exponent found but not allowed'",
154            Self::InvalidPositiveExponentSign(_) => "'invalid `+` sign in exponent'",
155            Self::MissingExponentSign(_) => "'missing required `+/-` sign for exponent'",
156            Self::ExponentWithoutFraction(_) =>  "'invalid float containing exponent without fraction'",
157            Self::InvalidLeadingZeros(_) => "'invalid number with leading zeros before digits'",
158            Self::MissingExponent(_) => "'missing required exponent'",
159            Self::MissingSign(_) => "'missing required `+/-` sign for integer'",
160            Self::InvalidPositiveSign(_) => "'invalid `+` sign for an integer was found'",
161            Self::InvalidNegativeSign(_) => "'invalid `-` sign for an unsigned type was found'",
162
163            // NUMBER FORMAT ERRORS
164            Self::InvalidMantissaRadix => "'invalid radix for mantissa digits'",
165            Self::InvalidExponentBase => "'invalid exponent base'",
166            Self::InvalidExponentRadix => "'invalid radix for exponent digits'",
167            Self::InvalidDigitSeparator => "'invalid digit separator: must be ASCII and not a digit or a `+/-` sign'",
168            Self::InvalidDecimalPoint => "'invalid decimal point: must be ASCII and not a digit or a `+/-` sign'",
169            Self::InvalidExponentSymbol => "'invalid exponent symbol: must be ASCII and not a digit or a `+/-` sign'",
170            Self::InvalidBasePrefix => "'invalid base prefix character'",
171            Self::InvalidBaseSuffix => "'invalid base suffix character'",
172            Self::InvalidPunctuation => "'invalid punctuation: multiple characters overlap'",
173            Self::InvalidExponentFlags => "'exponent flags set while disabling exponent notation'",
174            Self::InvalidMantissaSign => "'disabled the `+` sign while requiring a sign for significant digits'",
175            Self::InvalidExponentSign => "'disabled the `+` sign while requiring a sign for exponent digits'",
176            Self::InvalidSpecial => "'special flags set while disabling special floats'",
177            Self::InvalidConsecutiveIntegerDigitSeparator => "'enabled consecutive digit separators in the integer without setting a valid location'",
178            Self::InvalidConsecutiveFractionDigitSeparator => "'enabled consecutive digit separators in the fraction without setting a valid location'",
179            Self::InvalidConsecutiveExponentDigitSeparator => "'enabled consecutive digit separators in the exponent without setting a valid location'",
180            Self::InvalidFlags => "'invalid flags enabled without the format feature'",
181
182            // OPTION ERRORS
183            Self::InvalidNanString => "'NaN string must started with `n`'",
184            Self::NanStringTooLong => "'NaN string is too long'",
185            Self::InvalidInfString => "'short infinity string must started with `i`'",
186            Self::InfStringTooLong => "'short infinity string is too long'",
187            Self::InvalidInfinityString => "'long infinity string must started with `i`'",
188            Self::InfinityStringTooLong => "'long infinity string is too long'",
189            Self::InfinityStringTooShort => "'long infinity string is too short'",
190            Self::InvalidFloatParseAlgorithm => "'invalid combination of float parse algorithms'",
191            Self::InvalidRadix => "'invalid radix for significant digits'",
192            Self::InvalidFloatPrecision => "'invalid float precision: min digits is larger than max digits'",
193            Self::InvalidNegativeExponentBreak => "'invalid negative exponent break: value is above 0'",
194            Self::InvalidPositiveExponentBreak => "'invalid positive exponent break: value is below 0'",
195
196            // NOT AN ERROR
197            Self::Success => "'not actually an error'",
198        }
199    }
200
201    /// Get the index for the parsing error.
202    #[inline]
203    pub fn index(&self) -> Option<&usize> {
204        match self {
205            // PARSE ERRORS
206            Self::Overflow(index) => Some(index),
207            Self::Underflow(index) => Some(index),
208            Self::InvalidDigit(index) => Some(index),
209            Self::Empty(index) => Some(index),
210            Self::EmptyMantissa(index) => Some(index),
211            Self::EmptyExponent(index) => Some(index),
212            Self::EmptyInteger(index) => Some(index),
213            Self::EmptyFraction(index) => Some(index),
214            Self::InvalidPositiveMantissaSign(index) => Some(index),
215            Self::MissingMantissaSign(index) => Some(index),
216            Self::InvalidExponent(index) => Some(index),
217            Self::InvalidPositiveExponentSign(index) => Some(index),
218            Self::MissingExponentSign(index) => Some(index),
219            Self::ExponentWithoutFraction(index) => Some(index),
220            Self::InvalidLeadingZeros(index) => Some(index),
221            Self::MissingExponent(index) => Some(index),
222            Self::MissingSign(index) => Some(index),
223            Self::InvalidPositiveSign(index) => Some(index),
224            Self::InvalidNegativeSign(index) => Some(index),
225
226            // NUMBER FORMAT ERRORS
227            Self::InvalidMantissaRadix => None,
228            Self::InvalidExponentBase => None,
229            Self::InvalidExponentRadix => None,
230            Self::InvalidDigitSeparator => None,
231            Self::InvalidDecimalPoint => None,
232            Self::InvalidExponentSymbol => None,
233            Self::InvalidBasePrefix => None,
234            Self::InvalidBaseSuffix => None,
235            Self::InvalidPunctuation => None,
236            Self::InvalidExponentFlags => None,
237            Self::InvalidMantissaSign => None,
238            Self::InvalidExponentSign => None,
239            Self::InvalidSpecial => None,
240            Self::InvalidConsecutiveIntegerDigitSeparator => None,
241            Self::InvalidConsecutiveFractionDigitSeparator => None,
242            Self::InvalidConsecutiveExponentDigitSeparator => None,
243            Self::InvalidFlags => None,
244
245            // OPTION ERRORS
246            Self::InvalidNanString => None,
247            Self::NanStringTooLong => None,
248            Self::InvalidInfString => None,
249            Self::InfStringTooLong => None,
250            Self::InvalidInfinityString => None,
251            Self::InfinityStringTooLong => None,
252            Self::InfinityStringTooShort => None,
253            Self::InvalidFloatParseAlgorithm => None,
254            Self::InvalidRadix => None,
255            Self::InvalidFloatPrecision => None,
256            Self::InvalidNegativeExponentBreak => None,
257            Self::InvalidPositiveExponentBreak => None,
258
259            // NOT AN ERROR
260            Self::Success => None,
261        }
262    }
263
264    is_error_type!(is_overflow, Overflow(_));
265    is_error_type!(is_underflow, Underflow(_));
266    is_error_type!(is_invalid_digit, InvalidDigit(_));
267    is_error_type!(is_empty, Empty(_));
268    is_error_type!(is_empty_mantissa, EmptyMantissa(_));
269    is_error_type!(is_empty_exponent, EmptyExponent(_));
270    is_error_type!(is_empty_integer, EmptyInteger(_));
271    is_error_type!(is_empty_fraction, EmptyFraction(_));
272    is_error_type!(is_invalid_positive_mantissa_sign, InvalidPositiveMantissaSign(_));
273    is_error_type!(is_missing_mantissa_sign, MissingMantissaSign(_));
274    is_error_type!(is_invalid_exponent, InvalidExponent(_));
275    is_error_type!(is_invalid_positive_exponent_sign, InvalidPositiveExponentSign(_));
276    is_error_type!(is_missing_exponent_sign, MissingExponentSign(_));
277    is_error_type!(is_exponent_without_fraction, ExponentWithoutFraction(_));
278    is_error_type!(is_invalid_leading_zeros, InvalidLeadingZeros(_));
279    is_error_type!(is_missing_exponent, MissingExponent(_));
280    is_error_type!(is_missing_sign, MissingSign(_));
281    is_error_type!(is_invalid_positive_sign, InvalidPositiveSign(_));
282    is_error_type!(is_invalid_negative_sign, InvalidNegativeSign(_));
283    is_error_type!(is_invalid_mantissa_radix, InvalidMantissaRadix);
284    is_error_type!(is_invalid_exponent_base, InvalidExponentBase);
285    is_error_type!(is_invalid_exponent_radix, InvalidExponentRadix);
286    is_error_type!(is_invalid_digit_separator, InvalidDigitSeparator);
287    is_error_type!(is_invalid_decimal_point, InvalidDecimalPoint);
288    is_error_type!(is_invalid_exponent_symbol, InvalidExponentSymbol);
289    is_error_type!(is_invalid_base_prefix, InvalidBasePrefix);
290    is_error_type!(is_invalid_base_suffix, InvalidBaseSuffix);
291    is_error_type!(is_invalid_punctuation, InvalidPunctuation);
292    is_error_type!(is_invalid_exponent_flags, InvalidExponentFlags);
293    is_error_type!(is_invalid_mantissa_sign, InvalidMantissaSign);
294    is_error_type!(is_invalid_exponent_sign, InvalidExponentSign);
295    is_error_type!(is_invalid_special, InvalidSpecial);
296    is_error_type!(
297        is_invalid_consecutive_integer_digit_separator,
298        InvalidConsecutiveIntegerDigitSeparator
299    );
300    is_error_type!(
301        is_invalid_consecutive_fraction_digit_separator,
302        InvalidConsecutiveFractionDigitSeparator
303    );
304    is_error_type!(
305        is_invalid_consecutive_exponent_digit_separator,
306        InvalidConsecutiveExponentDigitSeparator
307    );
308    is_error_type!(is_invalid_flags, InvalidFlags);
309    is_error_type!(is_invalid_nan_string, InvalidNanString);
310    is_error_type!(is_nan_string_too_long, NanStringTooLong);
311    is_error_type!(is_invalid_inf_string, InvalidInfString);
312    is_error_type!(is_inf_string_too_long, InfStringTooLong);
313    is_error_type!(is_invalid_infinity_string, InvalidInfinityString);
314    is_error_type!(is_infinity_string_too_long, InfinityStringTooLong);
315    is_error_type!(is_infinity_string_too_short, InfinityStringTooShort);
316    is_error_type!(is_invalid_float_parse_algorithm, InvalidFloatParseAlgorithm);
317    is_error_type!(is_invalid_radix, InvalidRadix);
318    is_error_type!(is_invalid_float_precision, InvalidFloatPrecision);
319    is_error_type!(is_invalid_negative_exponent_break, InvalidNegativeExponentBreak);
320    is_error_type!(is_invalid_positive_exponent_break, InvalidPositiveExponentBreak);
321    is_error_type!(is_success, Success);
322}
323
324/// Add an error message for parsing errors.
325macro_rules! write_parse_error {
326    ($formatter:ident, $message:expr, $index:ident) => {
327        write!($formatter, "lexical parse error: {} at index {}", $message, $index)
328    };
329}
330
331/// Add an error message for number format errors.
332macro_rules! format_message {
333    ($formatter:ident, $message:expr) => {
334        write!($formatter, "lexical number format error: {}", $message)
335    };
336}
337
338/// Add an error message for options errors.
339macro_rules! options_message {
340    ($formatter:ident, $message:expr) => {
341        write!($formatter, "lexical options error: {}", $message)
342    };
343}
344
345impl fmt::Display for Error {
346    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
347        let description = self.description();
348        match self {
349            // PARSE ERRORS
350            Self::Overflow(index) => write_parse_error!(formatter, description, index),
351            Self::Underflow(index) => write_parse_error!(formatter, description, index),
352            Self::InvalidDigit(index) => write_parse_error!(formatter, description, index),
353            Self::Empty(index) => write_parse_error!(formatter, description, index),
354            Self::EmptyMantissa(index) => write_parse_error!(formatter, description, index),
355            Self::EmptyExponent(index) => write_parse_error!(formatter, description, index),
356            Self::EmptyInteger(index) => write_parse_error!(formatter, description, index),
357            Self::EmptyFraction(index) => write_parse_error!(formatter, description, index),
358            Self::InvalidPositiveMantissaSign(index) => {
359                write_parse_error!(formatter, description, index)
360            },
361            Self::MissingMantissaSign(index) => write_parse_error!(formatter, description, index),
362            Self::InvalidExponent(index) => write_parse_error!(formatter, description, index),
363            Self::InvalidPositiveExponentSign(index) => {
364                write_parse_error!(formatter, description, index)
365            },
366            Self::MissingExponentSign(index) => write_parse_error!(formatter, description, index),
367            Self::ExponentWithoutFraction(index) => {
368                write_parse_error!(formatter, description, index)
369            },
370            Self::InvalidLeadingZeros(index) => write_parse_error!(formatter, description, index),
371            Self::MissingExponent(index) => write_parse_error!(formatter, description, index),
372            Self::MissingSign(index) => write_parse_error!(formatter, description, index),
373            Self::InvalidPositiveSign(index) => write_parse_error!(formatter, description, index),
374            Self::InvalidNegativeSign(index) => write_parse_error!(formatter, description, index),
375
376            // NUMBER FORMAT ERRORS
377            Self::InvalidMantissaRadix => format_message!(formatter, description),
378            Self::InvalidExponentBase => format_message!(formatter, description),
379            Self::InvalidExponentRadix => format_message!(formatter, description),
380            Self::InvalidDigitSeparator => format_message!(formatter, description),
381            Self::InvalidDecimalPoint => format_message!(formatter, description),
382            Self::InvalidExponentSymbol => format_message!(formatter, description),
383            Self::InvalidBasePrefix => format_message!(formatter, description),
384            Self::InvalidBaseSuffix => format_message!(formatter, description),
385            Self::InvalidPunctuation => format_message!(formatter, description),
386            Self::InvalidExponentFlags => format_message!(formatter, description),
387            Self::InvalidMantissaSign => format_message!(formatter, description),
388            Self::InvalidExponentSign => format_message!(formatter, description),
389            Self::InvalidSpecial => format_message!(formatter, description),
390            Self::InvalidConsecutiveIntegerDigitSeparator => {
391                format_message!(formatter, description)
392            },
393            Self::InvalidConsecutiveFractionDigitSeparator => {
394                format_message!(formatter, description)
395            },
396            Self::InvalidConsecutiveExponentDigitSeparator => {
397                format_message!(formatter, description)
398            },
399            Self::InvalidFlags => format_message!(formatter, description),
400
401            // OPTION ERRORS
402            Self::InvalidNanString => options_message!(formatter, description),
403            Self::NanStringTooLong => options_message!(formatter, description),
404            Self::InvalidInfString => options_message!(formatter, description),
405            Self::InfStringTooLong => options_message!(formatter, description),
406            Self::InvalidInfinityString => options_message!(formatter, description),
407            Self::InfinityStringTooLong => options_message!(formatter, description),
408            Self::InfinityStringTooShort => options_message!(formatter, description),
409            Self::InvalidFloatParseAlgorithm => options_message!(formatter, description),
410            Self::InvalidRadix => options_message!(formatter, description),
411            Self::InvalidFloatPrecision => options_message!(formatter, description),
412            Self::InvalidNegativeExponentBreak => options_message!(formatter, description),
413            Self::InvalidPositiveExponentBreak => options_message!(formatter, description),
414
415            // NOT AN ERROR
416            Self::Success => write!(formatter, "{description}"),
417        }
418    }
419}
420
421#[cfg(feature = "std")]
422impl error::Error for Error {
423}