use core::{fmt, mem};
#[cfg(feature = "std")]
use std::error;
use static_assertions::const_assert;
#[non_exhaustive]
#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
pub enum Error {
Overflow(usize),
Underflow(usize),
InvalidDigit(usize),
Empty(usize),
EmptyMantissa(usize),
EmptyExponent(usize),
EmptyInteger(usize),
EmptyFraction(usize),
InvalidPositiveMantissaSign(usize),
MissingMantissaSign(usize),
InvalidExponent(usize),
InvalidPositiveExponentSign(usize),
MissingExponentSign(usize),
ExponentWithoutFraction(usize),
InvalidLeadingZeros(usize),
MissingExponent(usize),
MissingSign(usize),
InvalidPositiveSign(usize),
InvalidNegativeSign(usize),
InvalidMantissaRadix,
InvalidExponentBase,
InvalidExponentRadix,
InvalidDigitSeparator,
InvalidDecimalPoint,
InvalidExponentSymbol,
InvalidBasePrefix,
InvalidBaseSuffix,
InvalidPunctuation,
InvalidExponentFlags,
InvalidMantissaSign,
InvalidExponentSign,
InvalidSpecial,
InvalidConsecutiveIntegerDigitSeparator,
InvalidConsecutiveFractionDigitSeparator,
InvalidConsecutiveExponentDigitSeparator,
InvalidFlags,
InvalidNanString,
NanStringTooLong,
InvalidInfString,
InfStringTooLong,
InvalidInfinityString,
InfinityStringTooLong,
InfinityStringTooShort,
InvalidFloatParseAlgorithm,
InvalidRadix,
InvalidFloatPrecision,
InvalidNegativeExponentBreak,
InvalidPositiveExponentBreak,
Success,
}
const_assert!(mem::size_of::<Error>() <= 2 * mem::size_of::<usize>());
macro_rules! is_error_type {
($name:ident, $type:ident$($t:tt)*) => (
pub const fn $name(&self) -> bool {
if let Self::$type$($t)* = self {
true
} else {
false
}
}
);
}
impl Error {
pub fn index(&self) -> Option<&usize> {
match self {
Self::Overflow(index) => Some(index),
Self::Underflow(index) => Some(index),
Self::InvalidDigit(index) => Some(index),
Self::Empty(index) => Some(index),
Self::EmptyMantissa(index) => Some(index),
Self::EmptyExponent(index) => Some(index),
Self::EmptyInteger(index) => Some(index),
Self::EmptyFraction(index) => Some(index),
Self::InvalidPositiveMantissaSign(index) => Some(index),
Self::MissingMantissaSign(index) => Some(index),
Self::InvalidExponent(index) => Some(index),
Self::InvalidPositiveExponentSign(index) => Some(index),
Self::MissingExponentSign(index) => Some(index),
Self::ExponentWithoutFraction(index) => Some(index),
Self::InvalidLeadingZeros(index) => Some(index),
Self::MissingExponent(index) => Some(index),
Self::MissingSign(index) => Some(index),
Self::InvalidPositiveSign(index) => Some(index),
Self::InvalidNegativeSign(index) => Some(index),
Self::InvalidMantissaRadix => None,
Self::InvalidExponentBase => None,
Self::InvalidExponentRadix => None,
Self::InvalidDigitSeparator => None,
Self::InvalidDecimalPoint => None,
Self::InvalidExponentSymbol => None,
Self::InvalidBasePrefix => None,
Self::InvalidBaseSuffix => None,
Self::InvalidPunctuation => None,
Self::InvalidExponentFlags => None,
Self::InvalidMantissaSign => None,
Self::InvalidExponentSign => None,
Self::InvalidSpecial => None,
Self::InvalidConsecutiveIntegerDigitSeparator => None,
Self::InvalidConsecutiveFractionDigitSeparator => None,
Self::InvalidConsecutiveExponentDigitSeparator => None,
Self::InvalidFlags => None,
Self::InvalidNanString => None,
Self::NanStringTooLong => None,
Self::InvalidInfString => None,
Self::InfStringTooLong => None,
Self::InvalidInfinityString => None,
Self::InfinityStringTooLong => None,
Self::InfinityStringTooShort => None,
Self::InvalidFloatParseAlgorithm => None,
Self::InvalidRadix => None,
Self::InvalidFloatPrecision => None,
Self::InvalidNegativeExponentBreak => None,
Self::InvalidPositiveExponentBreak => None,
Self::Success => None,
}
}
is_error_type!(is_overflow, Overflow(_));
is_error_type!(is_underflow, Underflow(_));
is_error_type!(is_invalid_digit, InvalidDigit(_));
is_error_type!(is_empty, Empty(_));
is_error_type!(is_empty_mantissa, EmptyMantissa(_));
is_error_type!(is_empty_exponent, EmptyExponent(_));
is_error_type!(is_empty_integer, EmptyInteger(_));
is_error_type!(is_empty_fraction, EmptyFraction(_));
is_error_type!(is_invalid_positive_mantissa_sign, InvalidPositiveMantissaSign(_));
is_error_type!(is_missing_mantissa_sign, MissingMantissaSign(_));
is_error_type!(is_invalid_exponent, InvalidExponent(_));
is_error_type!(is_invalid_positive_exponent_sign, InvalidPositiveExponentSign(_));
is_error_type!(is_missing_exponent_sign, MissingExponentSign(_));
is_error_type!(is_exponent_without_fraction, ExponentWithoutFraction(_));
is_error_type!(is_invalid_leading_zeros, InvalidLeadingZeros(_));
is_error_type!(is_missing_exponent, MissingExponent(_));
is_error_type!(is_missing_sign, MissingSign(_));
is_error_type!(is_invalid_positive_sign, InvalidPositiveSign(_));
is_error_type!(is_invalid_negative_sign, InvalidNegativeSign(_));
is_error_type!(is_invalid_mantissa_radix, InvalidMantissaRadix);
is_error_type!(is_invalid_exponent_base, InvalidExponentBase);
is_error_type!(is_invalid_exponent_radix, InvalidExponentRadix);
is_error_type!(is_invalid_digit_separator, InvalidDigitSeparator);
is_error_type!(is_invalid_decimal_point, InvalidDecimalPoint);
is_error_type!(is_invalid_exponent_symbol, InvalidExponentSymbol);
is_error_type!(is_invalid_base_prefix, InvalidBasePrefix);
is_error_type!(is_invalid_base_suffix, InvalidBaseSuffix);
is_error_type!(is_invalid_punctuation, InvalidPunctuation);
is_error_type!(is_invalid_exponent_flags, InvalidExponentFlags);
is_error_type!(is_invalid_mantissa_sign, InvalidMantissaSign);
is_error_type!(is_invalid_exponent_sign, InvalidExponentSign);
is_error_type!(is_invalid_special, InvalidSpecial);
is_error_type!(
is_invalid_consecutive_integer_digit_separator,
InvalidConsecutiveIntegerDigitSeparator
);
is_error_type!(
is_invalid_consecutive_fraction_digit_separator,
InvalidConsecutiveFractionDigitSeparator
);
is_error_type!(
is_invalid_consecutive_exponent_digit_separator,
InvalidConsecutiveExponentDigitSeparator
);
is_error_type!(is_invalid_flags, InvalidFlags);
is_error_type!(is_invalid_nan_string, InvalidNanString);
is_error_type!(is_nan_string_too_long, NanStringTooLong);
is_error_type!(is_invalid_inf_string, InvalidInfString);
is_error_type!(is_inf_string_too_long, InfStringTooLong);
is_error_type!(is_invalid_infinity_string, InvalidInfinityString);
is_error_type!(is_infinity_string_too_long, InfinityStringTooLong);
is_error_type!(is_infinity_string_too_short, InfinityStringTooShort);
is_error_type!(is_invalid_float_parse_algorithm, InvalidFloatParseAlgorithm);
is_error_type!(is_invalid_radix, InvalidRadix);
is_error_type!(is_invalid_float_precision, InvalidFloatPrecision);
is_error_type!(is_invalid_negative_exponent_break, InvalidNegativeExponentBreak);
is_error_type!(is_invalid_positive_exponent_break, InvalidPositiveExponentBreak);
is_error_type!(is_success, Success);
}
macro_rules! write_parse_error {
($formatter:ident, $message:literal, $index:ident) => {
write!($formatter, "lexical parse error: {} at index {}", $message, $index)
};
}
macro_rules! format_message {
($formatter:ident, $message:literal) => {
write!($formatter, "lexical number format error: {}", $message)
};
}
macro_rules! options_message {
($formatter:ident, $message:literal) => {
write!($formatter, "lexical options error: {}", $message)
};
}
impl fmt::Display for Error {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Overflow(index) => write_parse_error!(formatter, "'numeric overflow occurred'", index),
Self::Underflow(index) => write_parse_error!(formatter, "'numeric underflow occurred'", index),
Self::InvalidDigit(index) => write_parse_error!(formatter, "'invalid digit found'", index),
Self::Empty(index) => write_parse_error!(formatter, "'the string to parse was empty'", index),
Self::EmptyMantissa(index) => write_parse_error!(formatter, "'no significant digits found'", index),
Self::EmptyExponent(index) => write_parse_error!(formatter, "'exponent notation found without an exponent'", index),
Self::EmptyInteger(index) => write_parse_error!(formatter, "'invalid float with no integer digits'", index),
Self::EmptyFraction(index) => write_parse_error!(formatter, "'invalid float with no fraction digits'", index),
Self::InvalidPositiveMantissaSign(index) => write_parse_error!(formatter, "'invalid `+` sign before significant digits'", index),
Self::MissingMantissaSign(index) => write_parse_error!(formatter, "'missing required `+/-` sign for significant digits'", index),
Self::InvalidExponent(index) => write_parse_error!(formatter, "'exponent found but not allowed'", index),
Self::InvalidPositiveExponentSign(index) => write_parse_error!(formatter, "'invalid `+` sign in exponent'", index),
Self::MissingExponentSign(index) => write_parse_error!(formatter, "'missing required `+/-` sign for exponent'", index),
Self::ExponentWithoutFraction(index) => write_parse_error!(formatter, "'invalid float containing exponent without fraction'", index),
Self::InvalidLeadingZeros(index) => write_parse_error!(formatter, "'invalid number with leading zeros before digits'", index),
Self::MissingExponent(index) => write_parse_error!(formatter, "'missing required exponent'", index),
Self::MissingSign(index) => write_parse_error!(formatter, "'missing required `+/-` sign for integer'", index),
Self::InvalidPositiveSign(index) => write_parse_error!(formatter, "'invalid `+` sign for an integer was found'", index),
Self::InvalidNegativeSign(index) => write_parse_error!(formatter, "'invalid `-` sign for an unsigned type was found'", index),
Self::InvalidMantissaRadix => format_message!(formatter, "'invalid radix for mantissa digits'"),
Self::InvalidExponentBase => format_message!(formatter, "'invalid exponent base'"),
Self::InvalidExponentRadix => format_message!(formatter, "'invalid radix for exponent digits'"),
Self::InvalidDigitSeparator => format_message!(formatter, "'invalid digit separator: must be ASCII and not a digit or a `+/-` sign'"),
Self::InvalidDecimalPoint => format_message!(formatter, "'invalid decimal point: must be ASCII and not a digit or a `+/-` sign'"),
Self::InvalidExponentSymbol => format_message!(formatter, "'invalid exponent symbol: must be ASCII and not a digit or a `+/-` sign'"),
Self::InvalidBasePrefix => format_message!(formatter, "'invalid base prefix character'"),
Self::InvalidBaseSuffix => format_message!(formatter, "'invalid base suffix character'"),
Self::InvalidPunctuation => format_message!(formatter, "'invalid punctuation: multiple characters overlap'"),
Self::InvalidExponentFlags => format_message!(formatter, "'exponent flags set while disabling exponent notation'"),
Self::InvalidMantissaSign => format_message!(formatter, "'disabled the `+` sign while requiring a sign for significant digits'"),
Self::InvalidExponentSign => format_message!(formatter, "'disabled the `+` sign while requiring a sign for exponent digits'"),
Self::InvalidSpecial => format_message!(formatter, "'special flags set while disabling special floats'"),
Self::InvalidConsecutiveIntegerDigitSeparator => format_message!(formatter, "'enabled consecutive digit separators in the integer without setting a valid location'"),
Self::InvalidConsecutiveFractionDigitSeparator => format_message!(formatter, "'enabled consecutive digit separators in the fraction without setting a valid location'"),
Self::InvalidConsecutiveExponentDigitSeparator => format_message!(formatter, "'enabled consecutive digit separators in the exponent without setting a valid location'"),
Self::InvalidFlags => format_message!(formatter, "'invalid flags enabled without the format feature'"),
Self::InvalidNanString => options_message!(formatter, "'NaN string must started with `n`'"),
Self::NanStringTooLong => options_message!(formatter, "'NaN string is too long'"),
Self::InvalidInfString => options_message!(formatter, "'short infinity string must started with `i`'"),
Self::InfStringTooLong => options_message!(formatter, "'short infinity string is too long'"),
Self::InvalidInfinityString => options_message!(formatter, "'long infinity string must started with `i`'"),
Self::InfinityStringTooLong => options_message!(formatter, "'long infinity string is too long'"),
Self::InfinityStringTooShort => options_message!(formatter, "'long infinity string is too short'"),
Self::InvalidFloatParseAlgorithm => options_message!(formatter, "'invalid combination of float parse algorithms'"),
Self::InvalidRadix => options_message!(formatter, "'invalid radix for significant digits'"),
Self::InvalidFloatPrecision => options_message!(formatter, "'invalid float precision: min digits is larger than max digits'"),
Self::InvalidNegativeExponentBreak => options_message!(formatter, "'invalid negative exponent break: value is above 0'"),
Self::InvalidPositiveExponentBreak => options_message!(formatter, "'invalid positive exponent break: value is below 0'"),
Self::Success => write!(formatter, "'not actually an error'"),
}
}
}
#[cfg(feature = "std")]
impl error::Error for Error {
}