1//! Error types for conversion to integral types.
23use crate::convert::Infallible;
4use crate::error::Error;
5use crate::fmt;
67/// The error type returned when a checked integral type conversion fails.
8#[stable(feature = "try_from", since = "1.34.0")]
9#[derive(Debug, Copy, Clone, PartialEq, Eq)]
10pub struct TryFromIntError(pub(crate) ());
1112#[stable(feature = "try_from", since = "1.34.0")]
13impl fmt::Display for TryFromIntError {
14fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
15#[allow(deprecated)]
16self.description().fmt(fmt)
17 }
18}
1920#[stable(feature = "try_from", since = "1.34.0")]
21impl Error for TryFromIntError {
22#[allow(deprecated)]
23fn description(&self) -> &str {
24"out of range integral type conversion attempted"
25}
26}
2728#[stable(feature = "try_from", since = "1.34.0")]
29impl From<Infallible> for TryFromIntError {
30fn from(x: Infallible) -> TryFromIntError {
31match x {}
32 }
33}
3435#[unstable(feature = "never_type", issue = "35121")]
36impl From<!> for TryFromIntError {
37#[inline]
38fn from(never: !) -> TryFromIntError {
39// Match rather than coerce to make sure that code like
40 // `From<Infallible> for TryFromIntError` above will keep working
41 // when `Infallible` becomes an alias to `!`.
42match never {}
43 }
44}
4546/// An error which can be returned when parsing an integer.
47///
48/// For example, this error is returned by the `from_str_radix()` functions
49/// on the primitive integer types (such as [`i8::from_str_radix`])
50/// and is used as the error type in their [`FromStr`] implementations.
51///
52/// [`FromStr`]: crate::str::FromStr
53///
54/// # Potential causes
55///
56/// Among other causes, `ParseIntError` can be thrown because of leading or trailing whitespace
57/// in the string e.g., when it is obtained from the standard input.
58/// Using the [`str::trim()`] method ensures that no whitespace remains before parsing.
59///
60/// # Example
61///
62/// ```
63/// if let Err(e) = i32::from_str_radix("a12", 10) {
64/// println!("Failed conversion to i32: {e}");
65/// }
66/// ```
67#[derive(Debug, Clone, PartialEq, Eq)]
68#[stable(feature = "rust1", since = "1.0.0")]
69pub struct ParseIntError {
70pub(super) kind: IntErrorKind,
71}
7273/// Enum to store the various types of errors that can cause parsing an integer to fail.
74///
75/// # Example
76///
77/// ```
78/// # fn main() {
79/// if let Err(e) = i32::from_str_radix("a12", 10) {
80/// println!("Failed conversion to i32: {:?}", e.kind());
81/// }
82/// # }
83/// ```
84#[stable(feature = "int_error_matching", since = "1.55.0")]
85#[derive(Debug, Clone, PartialEq, Eq, Copy, Hash)]
86#[non_exhaustive]
87pub enum IntErrorKind {
88/// Value being parsed is empty.
89 ///
90 /// This variant will be constructed when parsing an empty string.
91#[stable(feature = "int_error_matching", since = "1.55.0")]
92Empty,
93/// Contains an invalid digit in its context.
94 ///
95 /// Among other causes, this variant will be constructed when parsing a string that
96 /// contains a non-ASCII char.
97 ///
98 /// This variant is also constructed when a `+` or `-` is misplaced within a string
99 /// either on its own or in the middle of a number.
100#[stable(feature = "int_error_matching", since = "1.55.0")]
101InvalidDigit,
102/// Integer is too large to store in target integer type.
103#[stable(feature = "int_error_matching", since = "1.55.0")]
104PosOverflow,
105/// Integer is too small to store in target integer type.
106#[stable(feature = "int_error_matching", since = "1.55.0")]
107NegOverflow,
108/// Value was Zero
109 ///
110 /// This variant will be emitted when the parsing string has a value of zero, which
111 /// would be illegal for non-zero types.
112#[stable(feature = "int_error_matching", since = "1.55.0")]
113Zero,
114}
115116impl ParseIntError {
117/// Outputs the detailed cause of parsing an integer failing.
118#[must_use]
119 #[rustc_const_stable(feature = "const_int_from_str", since = "1.82.0")]
120 #[stable(feature = "int_error_matching", since = "1.55.0")]
121pub const fn kind(&self) -> &IntErrorKind {
122&self.kind
123 }
124}
125126#[stable(feature = "rust1", since = "1.0.0")]
127impl fmt::Display for ParseIntError {
128fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
129#[allow(deprecated)]
130self.description().fmt(f)
131 }
132}
133134#[stable(feature = "rust1", since = "1.0.0")]
135impl Error for ParseIntError {
136#[allow(deprecated)]
137fn description(&self) -> &str {
138match self.kind {
139 IntErrorKind::Empty => "cannot parse integer from empty string",
140 IntErrorKind::InvalidDigit => "invalid digit found in string",
141 IntErrorKind::PosOverflow => "number too large to fit in target type",
142 IntErrorKind::NegOverflow => "number too small to fit in target type",
143 IntErrorKind::Zero => "number would be zero for non-zero type",
144 }
145 }
146}