| //! User-facing API for float parsing. | |
| use crate::error::Error; | |
| use crate::fmt; | |
| use crate::num::imp::dec2flt; | |
| use crate::str::FromStr; | |
| macro_rules! from_str_float_impl { | |
| ($t:ty) => { | |
| #[stable(feature = "rust1", since = "1.0.0")] | |
| impl FromStr for $t { | |
| type Err = ParseFloatError; | |
| /// Converts a string in base 10 to a float. | |
| /// Accepts an optional decimal exponent. | |
| /// | |
| /// This function accepts strings such as | |
| /// | |
| /// * '3.14' | |
| /// * '-3.14' | |
| /// * '2.5E10', or equivalently, '2.5e10' | |
| /// * '2.5E-10' | |
| /// * '5.' | |
| /// * '.5', or, equivalently, '0.5' | |
| /// * '7' | |
| /// * '007' | |
| /// * 'inf', '-inf', '+infinity', 'NaN' | |
| /// | |
| /// Note that alphabetical characters are not case-sensitive. | |
| /// | |
| /// Leading and trailing whitespace represent an error. | |
| /// | |
| /// # Grammar | |
| /// | |
| /// All strings that adhere to the following [EBNF] grammar when | |
| /// lowercased will result in an [`Ok`] being returned: | |
| /// | |
| /// ```txt | |
| /// Float ::= Sign? ( 'inf' | 'infinity' | 'nan' | Number ) | |
| /// Number ::= ( Digit+ | | |
| /// Digit+ '.' Digit* | | |
| /// Digit* '.' Digit+ ) Exp? | |
| /// Exp ::= 'e' Sign? Digit+ | |
| /// Sign ::= [+-] | |
| /// Digit ::= [0-9] | |
| /// ``` | |
| /// | |
| /// [EBNF]: https://www.w3.org/TR/REC-xml/#sec-notation | |
| /// | |
| /// # Arguments | |
| /// | |
| /// * src - A string | |
| /// | |
| /// # Return value | |
| /// | |
| /// `Err(ParseFloatError)` if the string did not represent a valid | |
| /// number. Otherwise, `Ok(n)` where `n` is the closest | |
| /// representable floating-point number to the number represented | |
| /// by `src` (following the same rules for rounding as for the | |
| /// results of primitive operations). | |
| // We add the `#[inline(never)]` attribute, since its content will | |
| // be filled with that of `dec2flt`, which has #[inline(always)]. | |
| // Since `dec2flt` is generic, a normal inline attribute on this function | |
| // with `dec2flt` having no attributes results in heavily repeated | |
| // generation of `dec2flt`, despite the fact only a maximum of 2 | |
| // possible instances can ever exist. Adding #[inline(never)] avoids this. | |
| #[inline(never)] | |
| fn from_str(src: &str) -> Result<Self, ParseFloatError> { | |
| dec2flt::dec2flt(src) | |
| } | |
| } | |
| }; | |
| } | |
| #[cfg(target_has_reliable_f16)] | |
| from_str_float_impl!(f16); | |
| from_str_float_impl!(f32); | |
| from_str_float_impl!(f64); | |
| // FIXME(f16): A fallback is used when the backend+target does not support f16 well, in order | |
| // to avoid ICEs. | |
| #[cfg(not(target_has_reliable_f16))] | |
| #[expect(ineffective_unstable_trait_impl, reason = "stable trait on unstable type")] | |
| #[unstable(feature = "f16", issue = "116909")] | |
| impl FromStr for f16 { | |
| type Err = ParseFloatError; | |
| #[inline] | |
| fn from_str(_src: &str) -> Result<Self, ParseFloatError> { | |
| unimplemented!("requires target_has_reliable_f16") | |
| } | |
| } | |
| /// An error which can be returned when parsing a float. | |
| /// | |
| /// This error is used as the error type for the [`FromStr`] implementation | |
| /// for [`f32`] and [`f64`]. | |
| /// | |
| /// # Example | |
| /// | |
| /// ``` | |
| /// use std::str::FromStr; | |
| /// | |
| /// if let Err(e) = f64::from_str("a.12") { | |
| /// println!("Failed conversion to f64: {e}"); | |
| /// } | |
| /// ``` | |
| #[derive(Debug, Clone, PartialEq, Eq)] | |
| #[stable(feature = "rust1", since = "1.0.0")] | |
| pub struct ParseFloatError { | |
| pub(super) kind: FloatErrorKind, | |
| } | |
| #[derive(Debug, Clone, PartialEq, Eq)] | |
| pub(super) enum FloatErrorKind { | |
| Empty, | |
| Invalid, | |
| } | |
| #[stable(feature = "rust1", since = "1.0.0")] | |
| impl Error for ParseFloatError {} | |
| #[stable(feature = "rust1", since = "1.0.0")] | |
| impl fmt::Display for ParseFloatError { | |
| fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
| match self.kind { | |
| FloatErrorKind::Empty => "cannot parse float from empty string", | |
| FloatErrorKind::Invalid => "invalid float literal", | |
| } | |
| .fmt(f) | |
| } | |
| } |