Skip to main content

fastnum/bint/
error.rs

1use core::{
2    fmt,
3    fmt::{Debug, Display, Formatter},
4    num::{IntErrorKind, ParseIntError},
5};
6
7use crate::utils::err_prefix;
8
9/// Enum to store the various types of errors that can cause parsing `Big
10/// Integer` to fail.
11///
12/// # Example
13///
14/// ```
15/// use fastnum::U256;
16///
17/// if let Err(e) = U256::from_str_radix("a12", 10) {
18///     println!("Failed conversion to U256: {e}");
19/// }
20/// ```
21#[derive(Copy, Clone, PartialEq)]
22pub enum ParseError {
23    /// Value being parsed is empty.
24    ///
25    /// This variant will be constructed when parsing an empty string.
26    Empty,
27
28    /// Contains an invalid digit in its context.
29    ///
30    /// Among other causes, this variant will be constructed when parsing a
31    /// string that contains a non-ASCII char.
32    ///
33    /// This variant is also constructed when a `+` or `-` is misplaced within a
34    /// string either on its own or in the middle of a number.
35    InvalidDigit,
36
37    /// Integer is too large to store in target integer type.
38    PosOverflow,
39
40    /// Integer is too small to store in target integer type.
41    NegOverflow,
42
43    /// Value was Zero.
44    ///
45    /// This variant will be emitted when the parsing string has a value of
46    /// zero, which would be illegal for non-zero types.
47    Zero,
48
49    /// Value was Signed
50    ///
51    /// This variant will be emitted when the parsing string has a sign literal,
52    /// which would be illegal for unsigned types.
53    Signed,
54
55    /// Invalid radix.
56    InvalidRadix,
57
58    /// Unknown error.
59    Unknown,
60}
61
62impl ParseError {
63    pub(crate) const fn description(&self) -> &str {
64        use ParseError::*;
65        match self {
66            Empty => "attempt to parse integer from empty string",
67            InvalidDigit => "attempt to parse integer from string containing invalid digit",
68            PosOverflow => {
69                "attempt to parse integer too large to be represented by the target type"
70            }
71            NegOverflow => {
72                "attempt to parse integer too small to be represented by the target type"
73            }
74            Zero => {
75                "attempt to parse the integer `0` which cannot be represented by the target type"
76            }
77            Signed => "number would be signed for unsigned type",
78            InvalidRadix => "invalid radix",
79            Unknown => panic!("unknown error occurred"),
80        }
81    }
82}
83
84impl Display for ParseError {
85    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
86        write!(f, "{} {}", err_prefix!(), self.description())
87    }
88}
89
90impl Debug for ParseError {
91    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
92        Display::fmt(&self, f)
93    }
94}
95
96impl From<ParseIntError> for ParseError {
97    fn from(e: ParseIntError) -> ParseError {
98        from_int_error_kind(e.kind())
99    }
100}
101
102impl From<bnum::errors::ParseIntError> for ParseError {
103    fn from(e: bnum::errors::ParseIntError) -> Self {
104        from_int_error_kind(e.kind())
105    }
106}
107
108impl core::error::Error for ParseError {
109    fn description(&self) -> &str {
110        self.description()
111    }
112}
113
114pub(crate) const fn from_int_error_kind(e: &IntErrorKind) -> ParseError {
115    match e {
116        IntErrorKind::Empty => ParseError::Empty,
117        IntErrorKind::InvalidDigit => ParseError::InvalidDigit,
118        IntErrorKind::PosOverflow => ParseError::PosOverflow,
119        IntErrorKind::NegOverflow => ParseError::NegOverflow,
120        IntErrorKind::Zero => ParseError::Zero,
121        _ => ParseError::Unknown,
122    }
123}