Skip to main content

core/num/
float_parse.rs

1//! User-facing API for float parsing.
2
3use crate::error::Error;
4use crate::fmt;
5use crate::num::imp::dec2flt;
6use crate::str::FromStr;
7
8macro_rules! from_str_float_impl {
9    ($t:ty) => {
10        #[stable(feature = "rust1", since = "1.0.0")]
11        impl FromStr for $t {
12            type Err = ParseFloatError;
13
14            /// Converts a string in base 10 to a float.
15            /// Accepts an optional decimal exponent.
16            ///
17            /// This function accepts strings such as
18            ///
19            /// * '3.14'
20            /// * '-3.14'
21            /// * '2.5E10', or equivalently, '2.5e10'
22            /// * '2.5E-10'
23            /// * '5.'
24            /// * '.5', or, equivalently, '0.5'
25            /// * '7'
26            /// * '007'
27            /// * 'inf', '-inf', '+infinity', 'NaN'
28            ///
29            /// Note that alphabetical characters are not case-sensitive.
30            ///
31            /// Leading and trailing whitespace represent an error.
32            ///
33            /// # Grammar
34            ///
35            /// All strings that adhere to the following [EBNF] grammar when
36            /// lowercased will result in an [`Ok`] being returned:
37            ///
38            /// ```txt
39            /// Float  ::= Sign? ( 'inf' | 'infinity' | 'nan' | Number )
40            /// Number ::= ( Digit+ |
41            ///              Digit+ '.' Digit* |
42            ///              Digit* '.' Digit+ ) Exp?
43            /// Exp    ::= 'e' Sign? Digit+
44            /// Sign   ::= [+-]
45            /// Digit  ::= [0-9]
46            /// ```
47            ///
48            /// [EBNF]: https://www.w3.org/TR/REC-xml/#sec-notation
49            ///
50            /// # Arguments
51            ///
52            /// * src - A string
53            ///
54            /// # Return value
55            ///
56            /// `Err(ParseFloatError)` if the string did not represent a valid
57            /// number. Otherwise, `Ok(n)` where `n` is the closest
58            /// representable floating-point number to the number represented
59            /// by `src` (following the same rules for rounding as for the
60            /// results of primitive operations).
61            // We add the `#[inline(never)]` attribute, since its content will
62            // be filled with that of `dec2flt`, which has #[inline(always)].
63            // Since `dec2flt` is generic, a normal inline attribute on this function
64            // with `dec2flt` having no attributes results in heavily repeated
65            // generation of `dec2flt`, despite the fact only a maximum of 2
66            // possible instances can ever exist. Adding #[inline(never)] avoids this.
67            #[inline(never)]
68            fn from_str(src: &str) -> Result<Self, ParseFloatError> {
69                dec2flt::dec2flt(src)
70            }
71        }
72    };
73}
74
75#[cfg(target_has_reliable_f16)]
76from_str_float_impl!(f16);
77from_str_float_impl!(f32);
78from_str_float_impl!(f64);
79
80// FIXME(f16): A fallback is used when the backend+target does not support f16 well, in order
81// to avoid ICEs.
82
83#[cfg(not(target_has_reliable_f16))]
84#[expect(ineffective_unstable_trait_impl, reason = "stable trait on unstable type")]
85#[unstable(feature = "f16", issue = "116909")]
86impl FromStr for f16 {
87    type Err = ParseFloatError;
88
89    #[inline]
90    fn from_str(_src: &str) -> Result<Self, ParseFloatError> {
91        unimplemented!("requires target_has_reliable_f16")
92    }
93}
94
95/// An error which can be returned when parsing a float.
96///
97/// This error is used as the error type for the [`FromStr`] implementation
98/// for [`f32`] and [`f64`].
99///
100/// # Example
101///
102/// ```
103/// use std::str::FromStr;
104///
105/// if let Err(e) = f64::from_str("a.12") {
106///     println!("Failed conversion to f64: {e}");
107/// }
108/// ```
109#[derive(Debug, Clone, PartialEq, Eq)]
110#[stable(feature = "rust1", since = "1.0.0")]
111pub struct ParseFloatError {
112    pub(super) kind: FloatErrorKind,
113}
114
115/// An error kind which can be returned when parsing a float.
116///
117/// This error kind is used as the inner error type in [`ParseFloatError`] for the [`FromStr`] implementation
118/// for [`f32`] and [`f64`].
119///
120/// # Example
121///
122/// ```
123/// #![feature(extended_float_error_kind)]
124///
125/// use std::str::FromStr;
126///
127/// if let Err(e) = f64::from_str("a.12") {
128///     println!("Failed conversion to f64: {:?}", e.kind());
129/// }
130/// ```
131#[derive(Debug, Clone, PartialEq, Eq, Copy, Hash)]
132#[unstable(feature = "extended_float_error_kind", issue = "164793")]
133#[non_exhaustive]
134pub enum FloatErrorKind {
135    /// Cannot parse float from empty string.
136    #[unstable(feature = "extended_float_error_kind", issue = "164793")]
137    Empty,
138    /// Invalid float literal.
139    #[unstable(feature = "extended_float_error_kind", issue = "164793")]
140    Invalid,
141}
142
143impl ParseFloatError {
144    /// Outputs the detailed cause of parsing a float failing.
145    #[must_use]
146    #[inline]
147    #[rustc_const_unstable(feature = "extended_float_error_kind", issue = "164793")]
148    #[unstable(feature = "extended_float_error_kind", issue = "164793")]
149    pub const fn kind(&self) -> &FloatErrorKind {
150        &self.kind
151    }
152}
153
154#[stable(feature = "rust1", since = "1.0.0")]
155impl Error for ParseFloatError {}
156
157#[stable(feature = "rust1", since = "1.0.0")]
158impl fmt::Display for ParseFloatError {
159    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
160        match self.kind {
161            FloatErrorKind::Empty => "cannot parse float from empty string",
162            FloatErrorKind::Invalid => "invalid float literal",
163        }
164        .fmt(f)
165    }
166}