scanner_rust/scanner_u8_slice_ascii.rs
1use std::{char::REPLACEMENT_CHARACTER, str::FromStr};
2
3use crate::{ScannerError, kmp::find_boundary, text::numeric_text, whitespaces::*};
4
5/// A simple text scanner which can in-memory-ly parse primitive types and strings using ASCII from a byte slice.
6#[derive(Debug)]
7pub struct ScannerU8SliceAscii<'a> {
8 data: &'a [u8],
9 data_length: usize,
10 position: usize,
11}
12
13impl<'a> ScannerU8SliceAscii<'a> {
14 /// Create a scanner from in-memory bytes.
15 ///
16 /// ```rust
17 /// use std::io;
18 ///
19 /// use scanner_rust::ScannerU8SliceAscii;
20 ///
21 /// let mut sc = ScannerU8SliceAscii::new(b"123 456");
22 /// ```
23 #[inline]
24 pub fn new<D: ?Sized + AsRef<[u8]>>(data: &D) -> ScannerU8SliceAscii<'_> {
25 let data = data.as_ref();
26
27 ScannerU8SliceAscii {
28 data,
29 data_length: data.len(),
30 position: 0,
31 }
32 }
33}
34
35impl<'a> ScannerU8SliceAscii<'a> {
36 /// Read the next char. If the data is not a correct char, it will return a `Ok(Some(REPLACEMENT_CHARACTER))` which is �. If there is nothing to read, it will return `Ok(None)`.
37 ///
38 /// ```rust
39 /// use scanner_rust::ScannerU8SliceAscii;
40 ///
41 /// let mut sc = ScannerU8SliceAscii::new("5 c ab".as_bytes());
42 ///
43 /// assert_eq!(Some('5'), sc.next_char().unwrap());
44 /// assert_eq!(Some(' '), sc.next_char().unwrap());
45 /// assert_eq!(Some('c'), sc.next_char().unwrap());
46 /// assert_eq!(Some(' '), sc.next_char().unwrap());
47 /// assert_eq!(Some('a'), sc.next_char().unwrap());
48 /// assert_eq!(Some('b'), sc.next_char().unwrap());
49 /// assert_eq!(None, sc.next_char().unwrap());
50 /// ```
51 pub fn next_char(&mut self) -> Result<Option<char>, ScannerError> {
52 if self.position == self.data_length {
53 return Ok(None);
54 }
55
56 let e = self.data[self.position];
57
58 self.position += 1;
59
60 if e >= 128 { Ok(Some(REPLACEMENT_CHARACTER)) } else { Ok(Some(e as char)) }
61 }
62
63 /// Read the next line but not include the trailing line character (or line characters like `CrLf`(`\r\n`)). If there is nothing to read, it will return `Ok(None)`.
64 ///
65 /// ```rust
66 /// use scanner_rust::ScannerU8SliceAscii;
67 ///
68 /// let mut sc = ScannerU8SliceAscii::new("123 456\r\n789 \n\n ab ".as_bytes());
69 ///
70 /// assert_eq!(Some("123 456".as_bytes()), sc.next_line().unwrap());
71 /// assert_eq!(Some("789 ".as_bytes()), sc.next_line().unwrap());
72 /// assert_eq!(Some("".as_bytes()), sc.next_line().unwrap());
73 /// assert_eq!(Some(" ab ".as_bytes()), sc.next_line().unwrap());
74 /// ```
75 pub fn next_line(&mut self) -> Result<Option<&'a [u8]>, ScannerError> {
76 if self.position == self.data_length {
77 return Ok(None);
78 }
79
80 let mut p = self.position;
81
82 loop {
83 let e = self.data[p];
84
85 match e {
86 b'\n' => {
87 let data = &self.data[self.position..p];
88
89 if p + 1 < self.data_length && self.data[p + 1] == b'\r' {
90 self.position = p + 2;
91 } else {
92 self.position = p + 1;
93 }
94
95 return Ok(Some(data));
96 },
97 b'\r' => {
98 let data = &self.data[self.position..p];
99
100 if p + 1 < self.data_length && self.data[p + 1] == b'\n' {
101 self.position = p + 2;
102 } else {
103 self.position = p + 1;
104 }
105
106 return Ok(Some(data));
107 },
108 _ => (),
109 }
110
111 p += 1;
112
113 if p == self.data_length {
114 break;
115 }
116 }
117
118 let data = &self.data[self.position..p];
119
120 self.position = p;
121
122 Ok(Some(data))
123 }
124}
125
126impl<'a> ScannerU8SliceAscii<'a> {
127 /// Skip the next whitespaces (`javaWhitespace`). If there is nothing to read, it will return `Ok(false)`.
128 ///
129 /// ```rust
130 /// use scanner_rust::ScannerU8SliceAscii;
131 ///
132 /// let mut sc = ScannerU8SliceAscii::new("1 2 c".as_bytes());
133 ///
134 /// assert_eq!(Some('1'), sc.next_char().unwrap());
135 /// assert_eq!(Some(' '), sc.next_char().unwrap());
136 /// assert_eq!(Some('2'), sc.next_char().unwrap());
137 /// assert_eq!(true, sc.skip_whitespaces().unwrap());
138 /// assert_eq!(Some('c'), sc.next_char().unwrap());
139 /// assert_eq!(false, sc.skip_whitespaces().unwrap());
140 /// ```
141 pub fn skip_whitespaces(&mut self) -> Result<bool, ScannerError> {
142 if self.position == self.data_length {
143 return Ok(false);
144 }
145
146 loop {
147 if !is_whitespace_1(self.data[self.position]) {
148 break;
149 }
150
151 self.position += 1;
152
153 if self.position == self.data_length {
154 break;
155 }
156 }
157
158 Ok(true)
159 }
160
161 /// Read the next token separated by whitespaces. If there is nothing to read, it will return `Ok(None)`.
162 ///
163 /// ```rust
164 /// use scanner_rust::ScannerU8SliceAscii;
165 ///
166 /// let mut sc = ScannerU8SliceAscii::new("123 456\r\n789 \n\n ab ".as_bytes());
167 ///
168 /// assert_eq!(Some("123".as_bytes()), sc.next().unwrap());
169 /// assert_eq!(Some("456".as_bytes()), sc.next().unwrap());
170 /// assert_eq!(Some("789".as_bytes()), sc.next().unwrap());
171 /// assert_eq!(Some("ab".as_bytes()), sc.next().unwrap());
172 /// assert_eq!(None, sc.next().unwrap());
173 /// ```
174 #[allow(clippy::should_implement_trait)]
175 pub fn next(&mut self) -> Result<Option<&'a [u8]>, ScannerError> {
176 if !self.skip_whitespaces()? {
177 return Ok(None);
178 }
179
180 if self.position == self.data_length {
181 return Ok(None);
182 }
183
184 let mut p = self.position;
185
186 loop {
187 if is_whitespace_1(self.data[p]) {
188 let data = &self.data[self.position..p];
189
190 self.position = p;
191
192 return Ok(Some(data));
193 }
194
195 p += 1;
196
197 if p == self.data_length {
198 break;
199 }
200 }
201
202 let data = &self.data[self.position..p];
203
204 self.position = p;
205
206 Ok(Some(data))
207 }
208}
209
210impl<'a> ScannerU8SliceAscii<'a> {
211 /// Read the next bytes. If there is nothing to read, it will return `Ok(None)`.
212 ///
213 /// ```rust
214 /// use scanner_rust::ScannerU8SliceAscii;
215 ///
216 /// let mut sc = ScannerU8SliceAscii::new("123 456\r\n789 \n\n ab ".as_bytes());
217 ///
218 /// assert_eq!(Some("123".as_bytes()), sc.next_bytes(3).unwrap());
219 /// assert_eq!(Some(" 456".as_bytes()), sc.next_bytes(4).unwrap());
220 /// assert_eq!(Some("\r\n789 ".as_bytes()), sc.next_bytes(6).unwrap());
221 /// assert_eq!(Some("ab".as_bytes()), sc.next().unwrap());
222 /// assert_eq!(Some(" ".as_bytes()), sc.next_bytes(2).unwrap());
223 /// assert_eq!(None, sc.next_bytes(2).unwrap());
224 /// ```
225 pub fn next_bytes(
226 &mut self,
227 max_number_of_bytes: usize,
228 ) -> Result<Option<&'a [u8]>, ScannerError> {
229 if self.position == self.data_length {
230 return Ok(None);
231 }
232
233 let dropping_bytes = max_number_of_bytes.min(self.data_length - self.position);
234
235 let data = &self.data[self.position..(self.position + dropping_bytes)];
236
237 self.position += dropping_bytes;
238
239 Ok(Some(data))
240 }
241
242 /// Drop the next N bytes. If there is nothing to read, it will return `Ok(None)`. If there is something to read, it will return `Ok(Some(i))`. The `i` is the length of the actually dropped bytes.
243 ///
244 /// ```rust
245 /// use scanner_rust::ScannerU8SliceAscii;
246 ///
247 /// let mut sc = ScannerU8SliceAscii::new("123 456\r\n789 \n\n ab ".as_bytes());
248 ///
249 /// assert_eq!(Some(7), sc.drop_next_bytes(7).unwrap());
250 /// assert_eq!(Some("".as_bytes()), sc.next_line().unwrap());
251 /// assert_eq!(Some("789 ".as_bytes()), sc.next_line().unwrap());
252 /// assert_eq!(Some(1), sc.drop_next_bytes(1).unwrap());
253 /// assert_eq!(Some(" ab ".as_bytes()), sc.next_line().unwrap());
254 /// assert_eq!(None, sc.drop_next_bytes(1).unwrap());
255 /// ```
256 pub fn drop_next_bytes(
257 &mut self,
258 max_number_of_bytes: usize,
259 ) -> Result<Option<usize>, ScannerError> {
260 if self.position == self.data_length {
261 return Ok(None);
262 }
263
264 let dropping_bytes = max_number_of_bytes.min(self.data_length - self.position);
265
266 self.position += dropping_bytes;
267
268 Ok(Some(dropping_bytes))
269 }
270}
271
272impl<'a> ScannerU8SliceAscii<'a> {
273 /// Read the next data until it reaches a specific boundary. If there is nothing to read, it will return `Ok(None)`.
274 ///
275 /// An empty boundary reads all remaining data.
276 ///
277 /// ```rust
278 /// use scanner_rust::ScannerU8SliceAscii;
279 ///
280 /// let mut sc = ScannerU8SliceAscii::new("123 456\r\n789 \n\n ab ".as_bytes());
281 ///
282 /// assert_eq!(Some("123".as_bytes()), sc.next_until(" ").unwrap());
283 /// assert_eq!(Some("456\r".as_bytes()), sc.next_until("\n").unwrap());
284 /// assert_eq!(Some("78".as_bytes()), sc.next_until("9 ").unwrap());
285 /// assert_eq!(Some("\n\n ab ".as_bytes()), sc.next_until("kk").unwrap());
286 /// assert_eq!(None, sc.next().unwrap());
287 /// ```
288 pub fn next_until<D: ?Sized + AsRef<[u8]>>(
289 &mut self,
290 boundary: &D,
291 ) -> Result<Option<&'a [u8]>, ScannerError> {
292 if self.position == self.data_length {
293 return Ok(None);
294 }
295
296 let boundary = boundary.as_ref();
297 let boundary_length = boundary.len();
298
299 if boundary_length == 0 || boundary_length > self.data_length - self.position {
300 let data = &self.data[self.position..];
301
302 self.position = self.data_length;
303
304 return Ok(Some(data));
305 }
306
307 if let Some(offset) = find_boundary(&self.data[self.position..], boundary) {
308 let end = self.position + offset;
309 let data = &self.data[self.position..end];
310
311 self.position = end + boundary_length;
312
313 return Ok(Some(data));
314 }
315
316 let data = &self.data[self.position..];
317
318 self.position = self.data_length;
319
320 Ok(Some(data))
321 }
322}
323
324impl<'a> ScannerU8SliceAscii<'a> {
325 #[inline]
326 fn next_parse<T: FromStr>(&mut self) -> Result<Option<T>, ScannerError>
327 where
328 ScannerError: From<<T as FromStr>::Err>, {
329 let result = self.next()?;
330
331 match result {
332 Some(s) => Ok(Some(numeric_text(s).parse()?)),
333 None => Ok(None),
334 }
335 }
336}
337
338impl<'a> ScannerU8SliceAscii<'a> {
339 #[inline]
340 fn next_until_parse<T: FromStr, D: ?Sized + AsRef<[u8]>>(
341 &mut self,
342 boundary: &D,
343 ) -> Result<Option<T>, ScannerError>
344 where
345 ScannerError: From<<T as FromStr>::Err>, {
346 let result = self.next_until(boundary)?;
347
348 match result {
349 Some(s) => Ok(Some(numeric_text(s).parse()?)),
350 None => Ok(None),
351 }
352 }
353}
354
355macro_rules! scanner_u8_slice_ascii_number_methods {
356 ($(($t:ty, $next:ident, $next_until:ident, $sample:literal, $v1:literal, $v2:literal)),+ $(,)?) => {
357 impl<'a> ScannerU8SliceAscii<'a> {
358 $(
359 #[doc = concat!(
360 "Read the next token separated by whitespaces and parse it to a `", stringify!($t), "` value. If there is nothing to read, it will return `Ok(None)`.\n\n```rust\nuse scanner_rust::ScannerU8SliceAscii;\n\nlet mut sc = ScannerU8SliceAscii::new(", stringify!($sample), ".as_bytes());\n\nassert_eq!(Some(", stringify!($v1), "), sc.", stringify!($next), "().unwrap());\nassert_eq!(Some(", stringify!($v2), "), sc.", stringify!($next), "().unwrap());\n```"
361 )]
362 #[inline]
363 pub fn $next(&mut self) -> Result<Option<$t>, ScannerError> {
364 self.next_parse()
365 }
366 )+
367 }
368
369 impl<'a> ScannerU8SliceAscii<'a> {
370 $(
371 #[doc = concat!(
372 "Read the next text until it reaches a specific boundary and parse it to a `", stringify!($t), "` value. If there is nothing to read, it will return `Ok(None)`. An empty boundary reads all remaining data before parsing.\n\n```rust\nuse scanner_rust::ScannerU8SliceAscii;\n\nlet mut sc = ScannerU8SliceAscii::new(", stringify!($sample), ".as_bytes());\n\nassert_eq!(Some(", stringify!($v1), "), sc.", stringify!($next_until), "(\" \").unwrap());\nassert_eq!(Some(", stringify!($v2), "), sc.", stringify!($next_until), "(\" \").unwrap());\n```"
373 )]
374 #[inline]
375 pub fn $next_until<D: ?Sized + AsRef<[u8]>>(
376 &mut self,
377 boundary: &D,
378 ) -> Result<Option<$t>, ScannerError> {
379 self.next_until_parse(boundary)
380 }
381 )+
382 }
383 };
384}
385
386scanner_u8_slice_ascii_number_methods! {
387 (u8, next_u8, next_u8_until, "1 2", 1, 2),
388 (u16, next_u16, next_u16_until, "1 2", 1, 2),
389 (u32, next_u32, next_u32_until, "1 2", 1, 2),
390 (u64, next_u64, next_u64_until, "1 2", 1, 2),
391 (u128, next_u128, next_u128_until, "1 2", 1, 2),
392 (usize, next_usize, next_usize_until, "1 2", 1, 2),
393 (i8, next_i8, next_i8_until, "1 2", 1, 2),
394 (i16, next_i16, next_i16_until, "1 2", 1, 2),
395 (i32, next_i32, next_i32_until, "1 2", 1, 2),
396 (i64, next_i64, next_i64_until, "1 2", 1, 2),
397 (i128, next_i128, next_i128_until, "1 2", 1, 2),
398 (isize, next_isize, next_isize_until, "1 2", 1, 2),
399 (f32, next_f32, next_f32_until, "1 2.5", 1.0, 2.5),
400 (f64, next_f64, next_f64_until, "1 2.5", 1.0, 2.5),
401}
402
403impl<'a> ScannerU8SliceAscii<'a> {
404 /// Drop the next line but not include the trailing line character (or line characters like `CrLf`(`\r\n`)). If there is nothing to read, it will return `Ok(None)`. If there is something to read, it will return `Ok(Some(i))`. The `i` is the length (in bytes) of the dropped line.
405 ///
406 /// ```rust
407 /// use scanner_rust::ScannerU8SliceAscii;
408 ///
409 /// let mut sc = ScannerU8SliceAscii::new("123 456\r\n789 \n\n ab ".as_bytes());
410 ///
411 /// assert_eq!(Some(7), sc.drop_next_line().unwrap());
412 /// assert_eq!(Some("789 ".as_bytes()), sc.next_line().unwrap());
413 /// assert_eq!(Some(0), sc.drop_next_line().unwrap());
414 /// assert_eq!(Some(" ab ".as_bytes()), sc.next_line().unwrap());
415 /// assert_eq!(None, sc.drop_next_line().unwrap());
416 /// ```
417 #[inline]
418 pub fn drop_next_line(&mut self) -> Result<Option<usize>, ScannerError> {
419 Ok(self.next_line()?.map(<[u8]>::len))
420 }
421
422 /// Drop the next token separated by whitespaces. If there is nothing to read, it will return `Ok(None)`. If there is something to read, it will return `Ok(Some(i))`. The `i` is the length (in bytes) of the dropped token.
423 ///
424 /// ```rust
425 /// use scanner_rust::ScannerU8SliceAscii;
426 ///
427 /// let mut sc = ScannerU8SliceAscii::new("123 456\r\n789 \n\n ab ".as_bytes());
428 ///
429 /// assert_eq!(Some(3), sc.drop_next().unwrap());
430 /// assert_eq!(Some("456".as_bytes()), sc.next().unwrap());
431 /// assert_eq!(Some(3), sc.drop_next().unwrap());
432 /// assert_eq!(Some("ab".as_bytes()), sc.next().unwrap());
433 /// assert_eq!(None, sc.drop_next().unwrap());
434 /// ```
435 #[inline]
436 pub fn drop_next(&mut self) -> Result<Option<usize>, ScannerError> {
437 Ok(self.next()?.map(<[u8]>::len))
438 }
439
440 /// Drop the next data until it reaches a specific boundary. If there is nothing to read, it will return `Ok(None)`. If there is something to read, it will return `Ok(Some(i))`. The `i` is the length (in bytes) of the dropped data, excluding the boundary.
441 ///
442 /// An empty boundary drops all remaining data.
443 ///
444 /// ```rust
445 /// use scanner_rust::ScannerU8SliceAscii;
446 ///
447 /// let mut sc = ScannerU8SliceAscii::new("123 456\r\n789 \n\n ab ".as_bytes());
448 ///
449 /// assert_eq!(Some(7), sc.drop_next_until("\r\n").unwrap());
450 /// assert_eq!(Some("789 ".as_bytes()), sc.next_line().unwrap());
451 /// assert_eq!(Some(0), sc.drop_next_until("\n").unwrap());
452 /// assert_eq!(Some(" ab ".as_bytes()), sc.next_line().unwrap());
453 /// assert_eq!(None, sc.drop_next_until("").unwrap());
454 /// ```
455 #[inline]
456 pub fn drop_next_until<D: ?Sized + AsRef<[u8]>>(
457 &mut self,
458 boundary: &D,
459 ) -> Result<Option<usize>, ScannerError> {
460 Ok(self.next_until(boundary)?.map(<[u8]>::len))
461 }
462}
463
464impl<'a> Iterator for ScannerU8SliceAscii<'a> {
465 type Item = &'a [u8];
466
467 #[inline]
468 fn next(&mut self) -> Option<Self::Item> {
469 self.next().unwrap_or(None)
470 }
471}