1 //! C-compatible error type.
2 
3 use crate::lib::fmt::{self, Display, Formatter};
4 
5 #[cfg(feature = "std")]
6 use std::error::Error as StdError;
7 
8 /// Error code, indicating failure type.
9 ///
10 /// Error messages are designating by an error code of less than 0.
11 /// This is to be compatible with C conventions. This enumeration is
12 /// FFI-compatible for interfacing with C code.
13 ///
14 /// # FFI
15 ///
16 /// For interfacing with FFI-code, this may be approximated by:
17 /// ```text
18 /// const int32_t OVERFLOW = -1;
19 /// const int32_t UNDERFLOW = -2;
20 /// const int32_t INVALID_DIGIT = -3;
21 /// const int32_t EMPTY = -4;
22 /// const int32_t EMPTY_FRACTION = -5;
23 /// const int32_t EMPTY_EXPONENT = -6;
24 /// ```
25 ///
26 /// # Safety
27 ///
28 /// Assigning any value outside the range `[-6, -1]` to value of type
29 /// ErrorCode may invoke undefined-behavior.
30 #[repr(i32)]
31 #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
32 pub enum ErrorCode {
33     /// Integral overflow occurred during numeric parsing.
34     ///
35     /// Numeric overflow takes precedence over the presence of an invalid
36     /// digit.
37     Overflow = -1,
38     /// Integral underflow occurred during numeric parsing.
39     ///
40     /// Numeric overflow takes precedence over the presence of an invalid
41     /// digit.
42     Underflow = -2,
43     /// Invalid digit found before string termination.
44     InvalidDigit = -3,
45     /// Empty byte array found.
46     Empty = -4,
47     /// Empty mantissa found.
48     EmptyMantissa = -5,
49     /// Empty exponent found.
50     EmptyExponent = -6,
51     /// Empty integer found.
52     EmptyInteger = -7,
53     /// Empty fraction found.
54     EmptyFraction = -8,
55     /// Invalid positive mantissa sign was found.
56     InvalidPositiveMantissaSign = -9,
57     /// Mantissa sign was required, but not found.
58     MissingMantissaSign = -10,
59     /// Exponent was present but not allowed.
60     InvalidExponent = -11,
61     /// Invalid positive exponent sign was found.
62     InvalidPositiveExponentSign = -12,
63     /// Exponent sign was required, but not found.
64     MissingExponentSign = -13,
65     /// Exponent was present without fraction component.
66     ExponentWithoutFraction = -14,
67     /// Integer had invalid leading zeros.
68     InvalidLeadingZeros = -15,
69 
70     // We may add additional variants later, so ensure that client matching
71     // does not depend on exhaustive matching.
72     #[doc(hidden)]
73     __Nonexhaustive = -200,
74 }
75 
76 /// Error type for lexical parsing.
77 ///
78 /// This error is FFI-compatible for interfacing with C code.
79 #[repr(C)]
80 #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
81 pub struct Error {
82     /// Error code designating the type of error occurred.
83     pub code: ErrorCode,
84     /// Optional position within the buffer for the error.
85     pub index: usize,
86 }
87 
88 impl From<ErrorCode> for Error {
89     #[inline]
from(code: ErrorCode) -> Self90     fn from(code: ErrorCode) -> Self {
91         Error { code: code, index: 0 }
92     }
93 }
94 
95 impl From<(ErrorCode, usize)> for Error {
96     #[inline]
from(error: (ErrorCode, usize)) -> Self97     fn from(error: (ErrorCode, usize)) -> Self {
98         Error { code: error.0, index: error.1 }
99     }
100 }
101 
102 impl Display for Error {
fmt(&self, f: &mut Formatter<'_>) -> fmt::Result103     fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
104         write!(f, "lexical error: {:?} at index {}.", self.code, self.index)
105     }
106 }
107 
108 #[cfg(feature = "std")]
109 impl StdError for Error {}
110