1//! User-facing API for float parsing.
23use crate::error::Error;
4use crate::fmt;
5use crate::num::imp::dec2flt;
6use crate::str::FromStr;
78macro_rules!from_str_float_impl {
9 ($t:ty) => {
10#[stable(feature = "rust1", since = "1.0.0")]
11impl FromStr for $t {
12type Err = ParseFloatError;
1314/// 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)]
68fn from_str(src: &str) -> Result<Self, ParseFloatError> {
69 dec2flt::dec2flt(src)
70 }
71 }
72 };
73}
7475#[cfg(target_has_reliable_f16)]
76#[stable(feature = "rust1", since = "1.0.0")]
impl FromStr for f16 {
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).
#[inline(never)]
fn from_str(src: &str) -> Result<Self, ParseFloatError> {
dec2flt::dec2flt(src)
}
}from_str_float_impl!(f16);
77#[stable(feature = "rust1", since = "1.0.0")]
impl FromStr for f32 {
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).
#[inline(never)]
fn from_str(src: &str) -> Result<Self, ParseFloatError> {
dec2flt::dec2flt(src)
}
}from_str_float_impl!(f32);
78#[stable(feature = "rust1", since = "1.0.0")]
impl FromStr for f64 {
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).
#[inline(never)]
fn from_str(src: &str) -> Result<Self, ParseFloatError> {
dec2flt::dec2flt(src)
}
}from_str_float_impl!(f64);
7980// FIXME(f16): A fallback is used when the backend+target does not support f16 well, in order
81// to avoid ICEs.
8283#[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 {
87type Err = ParseFloatError;
8889#[inline]
90fn from_str(_src: &str) -> Result<Self, ParseFloatError> {
91unimplemented!("requires target_has_reliable_f16")
92 }
93}
9495/// 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(#[automatically_derived]
#[stable(feature = "rust1", since = "1.0.0")]
impl crate::fmt::Debug for ParseFloatError {
#[inline]
fn fmt(&self, f: &mut crate::fmt::Formatter) -> crate::fmt::Result {
crate::fmt::Formatter::debug_struct_field1_finish(f,
"ParseFloatError", "kind", &&self.kind)
}
}Debug, #[automatically_derived]
#[stable(feature = "rust1", since = "1.0.0")]
impl crate::clone::Clone for ParseFloatError {
#[inline]
fn clone(&self) -> ParseFloatError {
ParseFloatError { kind: crate::clone::Clone::clone(&self.kind) }
}
}Clone, #[automatically_derived]
#[stable(feature = "rust1", since = "1.0.0")]
impl crate::cmp::PartialEq for ParseFloatError {
#[inline]
fn eq(&self, other: &ParseFloatError) -> bool { self.kind == other.kind }
}PartialEq, #[automatically_derived]
#[stable(feature = "rust1", since = "1.0.0")]
impl crate::cmp::Eq for ParseFloatError {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: crate::cmp::AssertParamIsEq<FloatErrorKind>;
}
}Eq)]
110#[stable(feature = "rust1", since = "1.0.0")]
111pub struct ParseFloatError {
112pub(super) kind: FloatErrorKind,
113}
114115#[derive(#[automatically_derived]
impl crate::fmt::Debug for FloatErrorKind {
#[inline]
fn fmt(&self, f: &mut crate::fmt::Formatter) -> crate::fmt::Result {
crate::fmt::Formatter::write_str(f,
match self {
FloatErrorKind::Empty => "Empty",
FloatErrorKind::Invalid => "Invalid",
})
}
}Debug, #[automatically_derived]
impl crate::clone::Clone for FloatErrorKind {
#[inline]
fn clone(&self) -> FloatErrorKind {
match self {
FloatErrorKind::Empty => FloatErrorKind::Empty,
FloatErrorKind::Invalid => FloatErrorKind::Invalid,
}
}
}Clone, #[automatically_derived]
impl crate::cmp::PartialEq for FloatErrorKind {
#[inline]
fn eq(&self, other: &FloatErrorKind) -> bool {
let __self_discr = crate::intrinsics::discriminant_value(self);
let __arg1_discr = crate::intrinsics::discriminant_value(other);
__self_discr == __arg1_discr
}
}PartialEq, #[automatically_derived]
impl crate::cmp::Eq for FloatErrorKind {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {}
}Eq)]
116pub(super) enum FloatErrorKind {
117 Empty,
118 Invalid,
119}
120121#[stable(feature = "rust1", since = "1.0.0")]
122impl Errorfor ParseFloatError {}
123124#[stable(feature = "rust1", since = "1.0.0")]
125impl fmt::Displayfor ParseFloatError {
126fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
127match self.kind {
128 FloatErrorKind::Empty => "cannot parse float from empty string",
129 FloatErrorKind::Invalid => "invalid float literal",
130 }
131 .fmt(f)
132 }
133}