iof/read/impls/
float.rs

1use crate::impl_read_one_from_for_from_str;
2
3#[cfg(feature = "c-compatible")]
4mod inner {
5    use crate::ext::{Pattern, State};
6
7    /// See <https://doc.rust-lang.org/std/primitive.f64.html#impl-FromStr-for-f64>
8    #[derive(Debug, Clone, Copy, Default)]
9    pub(super) enum Float {
10        #[default]
11        Initial,
12        /// `Sign`.
13        Sign,
14
15        /// `Sign? 'i'`.
16        I,
17        /// `Sign? 'in'`.
18        In,
19        /// `Sign? 'inf'`.
20        Inf,
21        /// `Sign? 'infi'`.
22        Infi,
23        /// `Sign? 'infin'`.
24        Infin,
25        /// `Sign? 'infini'`.
26        Infini,
27        /// `Sign? 'infinit'`.
28        Infinit,
29        /// `Sign? 'infinity'`.
30        Infinity,
31
32        /// `Sign? 'n'`.
33        N,
34        /// `Sign? 'na'`.
35        Na,
36        /// `Sign? 'nan'`.
37        Nan,
38
39        /// `Sign? Digit+`.
40        Digits,
41        /// `Sign? Dot`.
42        Dot,
43        /// `Sign? Digit+ Dot`.
44        DotAfterDigits,
45        /// `Sign? Digit* Dot Digit+`.
46        DigitsAfterDot,
47        /// `Sign? (Digit+ | Digit+ Dot Digit* | Digit* Dot Digit+) 'e'`.
48        Exponent,
49        /// `Sign? (Digit+ | Digit+ Dot Digit* | Digit* Dot Digit+) 'e' Sign`.
50        SignAfterExponent,
51        /// `Sign? (Digit+ | Digit+ Dot Digit* | Digit* Dot Digit+) 'e' Sign? Digit+`.
52        DigitAfterExponent,
53        // Overrun,
54    }
55
56    impl Pattern for Float {
57        type Item = char;
58
59        #[inline]
60        fn step(&mut self, c: <Self as Pattern>::Item) -> bool {
61            match self {
62                Self::Initial => match c {
63                    '+' | '-' => *self = Self::Sign,
64                    '.' => *self = Self::Dot,
65                    _ if c.is_ascii_digit() => *self = Self::Digits,
66                    'I' | 'i' => *self = Self::I,
67                    'N' | 'n' => *self = Self::N,
68                    _ => return false,
69                },
70                Self::Sign => match c {
71                    '.' => *self = Self::Dot,
72                    _ if c.is_ascii_digit() => *self = Self::Digits,
73                    'I' | 'i' => *self = Self::I,
74                    'N' | 'n' => *self = Self::N,
75                    _ => return false,
76                },
77                Self::I => {
78                    match c {
79                        'N' | 'n' => *self = Self::In,
80                        _ => return false,
81                    }
82                    // if c.is_ascii_digit() {
83                    //     Ok(false)
84                    // } else {
85                    //     Err(PatternError::UnexpectedChar(c))
86                    // }
87                }
88                Self::In => match c {
89                    'F' | 'f' => *self = Self::Inf,
90                    _ => return false,
91                },
92                Self::Inf => match c {
93                    'I' | 'i' => *self = Self::Infi,
94                    _ => return false,
95                },
96                Self::Infi => match c {
97                    'N' | 'n' => *self = Self::Infin,
98                    _ => return false,
99                },
100                Self::Infin => match c {
101                    'I' | 'i' => *self = Self::Infini,
102                    _ => return false,
103                },
104                Self::Infini => match c {
105                    'T' | 't' => *self = Self::Infinit,
106                    _ => return false,
107                },
108                Self::Infinit => match c {
109                    'Y' | 'y' => *self = Self::Infinity,
110                    _ => return false,
111                },
112                Self::Infinity => return false,
113                Self::N => match c {
114                    'A' | 'a' => *self = Self::Na,
115                    _ => return false,
116                },
117                Self::Na => match c {
118                    'N' | 'n' => *self = Self::Nan,
119                    _ => return false,
120                },
121                Self::Nan => return false,
122                Self::Digits => match c {
123                    '.' => *self = Self::DotAfterDigits,
124                    'e' | 'E' => *self = Self::Exponent,
125                    _ if c.is_ascii_digit() => {}
126                    _ => return false,
127                },
128                Self::Dot | Self::DotAfterDigits => match c {
129                    'e' | 'E' => *self = Self::Exponent,
130                    _ if c.is_ascii_digit() => *self = Self::DigitsAfterDot,
131                    _ => return false,
132                },
133                Self::DigitsAfterDot => match c {
134                    'e' | 'E' => *self = Self::Exponent,
135                    _ if c.is_ascii_digit() => {}
136                    _ => return false,
137                },
138                Self::Exponent => {
139                    match c {
140                        '+' | '-' => *self = Self::SignAfterExponent,
141                        _ if c.is_ascii_digit() => *self = Self::DigitAfterExponent,
142                        _ => return false,
143                    }
144                    // if c == '+' || c == '-' {
145                    //     *self = Self::Alphabet;
146                    //     Ok(true)
147                    // } else if c.is_ascii_digit() {
148                    //     Ok(false)
149                    // } else {
150                    //     Err(PatternError::UnexpectedChar(c))
151                    // }
152                }
153                Self::SignAfterExponent => match c {
154                    _ if c.is_ascii_digit() => *self = Self::DigitAfterExponent,
155                    _ => return false,
156                },
157                Self::DigitAfterExponent => match c {
158                    _ if c.is_ascii_digit() => {}
159                    _ => return false,
160                },
161                // Self::Overrun => {}
162            }
163            true
164        }
165
166        #[inline]
167        fn state(&self) -> State {
168            match self {
169                Self::Inf
170                | Self::Infinity
171                | Self::Nan
172                | Self::Digits
173                | Self::DotAfterDigits
174                | Self::DigitsAfterDot
175                | Self::DigitAfterExponent => State::Stoppable,
176                // Self::Overrun => State::Overrun,
177                _ => State::Unfulfilled,
178            }
179        }
180    }
181}
182
183// See <https://doc.rust-lang.org/std/primitive.f64.html#impl-FromStr-for-f64>
184#[cfg(feature = "c-compatible")]
185impl_read_one_from_for_from_str!(
186    f32 f64 => inner::Float::Initial
187);
188
189#[cfg(not(feature = "c-compatible"))]
190impl_read_one_from_for_from_str!(f32 f64);