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