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);