1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
//! Helper functions that can be used when working with `Tokens<Item=char>`.
use crateTokens;
/// If the next tokens are either `\n` (like on linux) or `\r\n` (like on windows),
/// this will consume then and return `Some("\n")` or `Some("\r\n")` respectively.
/// If the next tokens are not one of these, then `None` will be returned and nothing
/// will be consumed.
///
/// # Example
///
/// ```
/// use yap::{Tokens, IntoTokens, chars};
///
/// let mut toks = "\r\n abc".into_tokens();
///
/// assert_eq!(chars::line_ending(&mut toks), Some("\r\n"));
/// assert_eq!(toks.remaining(), " abc");
///
/// let mut toks = "\n abc".into_tokens();
///
/// assert_eq!(chars::line_ending(&mut toks), Some("\n"));
/// assert_eq!(toks.remaining(), " abc");
///
/// let mut toks = "abc".into_tokens();
///
/// assert_eq!(chars::line_ending(&mut toks), None);
/// assert_eq!(toks.remaining(), "abc");
/// ```
/// If the next tokens are a valid Rust floating point number (see [`float`]
/// for more details), then consume them and return them as an [`f32`]. Else,
/// don't consume anything and return `None`.
///
/// Like [`Tokens::parse`], the generic parameter `Buf` indicates the type of buffer
/// that may be used to collect tokens prior to parsing. Implementations like
/// [`crate::types::StrTokens`] are optimised to avoid using a buffer in
/// many cases.
///
/// # Example
///
/// ```
/// use yap::{Tokens, IntoTokens, chars};
///
/// let mut toks = "3.14 hi".into_tokens();
///
/// let n = chars::parse_f64::<String>(&mut toks).unwrap();
/// assert_eq!(toks.remaining(), " hi");
/// ```
/// If the next tokens are a valid Rust floating point number (see [`float`]
/// for more details), then consume them and return them as an [`f32`]. Else,
/// don't consume anything and return `None`.
///
/// Like [`Tokens::parse`], the generic parameter `Buf` indicates the type of buffer
/// that may be used to collect tokens prior to parsing. Implementations like
/// [`crate::types::StrTokens`] are optimised to avoid using a buffer in
/// many cases.
///
/// # Example
///
/// ```
/// use yap::{Tokens, IntoTokens, chars};
///
/// let mut toks = "3.14 hi".into_tokens();
///
/// let n = chars::parse_f32::<String>(&mut toks).unwrap();
/// assert_eq!(toks.remaining(), " hi");
/// ```
// Parse an f32 or f64 from the input, returning None if the input
// did not contain a valid rust style float. This is expected to be
// used only to parse f32s or f64s and may panic otherwise.
/// If the next tokens represent a base10 float that would be successfully parsed with
/// `s.parse::<f32>()` or `s.parse::<f64>()`, then they will be consumed and `true` returned.
/// Otherwise, `false` is returned and nothing is consumed.
///
/// Rust float parsing is quite permissive in general. Strings such as these will be treated
/// as valid floats and fully consumed:
///
/// * '3.14'
/// * '-3.14'
/// * '2.5E10', or equivalently, '2.5e10'
/// * '2.5E-10'
/// * '5.'
/// * '.5', or, equivalently, '0.5'
/// * 'inf', '-inf', '+infinity', 'NaN'
///
/// Note that alphabetical characters are not case-sensitive.
///
/// More specifically, all strings that adhere to the following EBNF grammar when
/// lowercased will be consumed, and `true` returned:
///
/// ```txt
/// Float ::= Sign? ( 'inf' | 'infinity' | 'nan' | Number )
/// Number ::= ( Digit+ |
/// Digit+ '.' Digit* |
/// Digit* '.' Digit+ ) Exp?
/// Exp ::= 'e' Sign? Digit+
/// Sign ::= [+-]
/// Digit ::= [0-9]
/// ```
///
/// # Example
///
/// ```
/// use yap::{Tokens, IntoTokens, chars};
/// use core::str::FromStr;
///
/// // These will all be fully consumed as valid floats:
/// let valid_numbers = [
/// "3.14",
/// "-3.14",
/// "2.5E10",
/// "2.5e-10",
/// "2.5e+10",
/// "+3.123e12",
/// "5.",
/// ".5",
/// "+.5",
/// "0.5",
/// "inf",
/// "NaN",
/// "-infinity",
/// "+infinity",
/// "INFINITY",
/// ];
///
/// for n in valid_numbers {
/// let mut toks = n.into_tokens();
///
/// assert!(chars::float(&mut toks), "failed to parse: {}", n);
/// assert_eq!(toks.remaining(), "");
///
/// n.parse::<f64>().expect("Rust can parse the string, too");
/// }
///
/// // These are all invalid and won't be consumed:
/// let invalid_numbers = [
/// // Spaces aren't consumed:
/// " 3.14",
/// // Need a number one side of a decimal point:
/// ".",
/// // The "e" won't be consumed, since nothing follows it:
/// "3e"
/// ];
///
/// for n in invalid_numbers {
/// let mut toks = n.into_tokens();
///
/// assert!(!chars::float(&mut toks), "succeeded in parsing: {}", n);
/// assert!(toks.remaining().len() > 0);
///
/// n.parse::<f64>().unwrap_err();
/// }
/// ```
/// If the next tokens are equal (case insensitive) to the string provided,
/// this returns `true` and consumes the tokens. Else, it returns `false` and
/// doesn't consume anything.
///
/// # Example
///
/// ```
/// use yap::{Tokens, IntoTokens, chars};
///
/// let mut toks = "HeLlO".into_tokens();
///
/// assert_eq!(chars::case_insensitive_eq(&mut toks, "hello"), true);
/// assert_eq!(toks.remaining(), "");
///
/// let mut toks = "Howdy".into_tokens();
///
/// assert_eq!(chars::case_insensitive_eq(&mut toks, "hello"), false);
/// assert_eq!(toks.remaining(), "Howdy");
/// ```