yap/tokens.rs
1//! The point of this library. This module contains the core [`Tokens`] trait, which adds
2//! various convenience methods on top of an [`Iterator`] based interface aimed at making
3//! it easy to parse things.
4//!
5//! The [`IntoTokens`] trait is also provided, and can be implemented for types that can be
6//! converted into something implementing the [`Tokens`] trait (for example `&str` and `&[T]`).
7mod many;
8mod many_err;
9mod sep_by;
10mod sep_by_all;
11mod sep_by_all_err;
12mod sep_by_err;
13mod slice;
14mod take;
15mod take_while;
16
17use core::borrow::Borrow;
18use core::ops::Deref;
19use core::str::FromStr;
20
21// Re-export the structs handed back from token fns:
22pub use many::Many;
23pub use many_err::ManyErr;
24pub use sep_by::SepBy;
25pub use sep_by_all::SepByAll;
26pub use sep_by_all_err::SepByAllErr;
27pub use sep_by_err::SepByErr;
28pub use slice::Slice;
29pub use take::Take;
30pub use take_while::TakeWhile;
31
32use crate::types::{WithContext, WithContextMut};
33
34/// The tokens trait is an extension of the [`Iterator`] trait, and adds a bunch of useful methods
35/// for parsing tokens from the underlying iterable type.
36///
37/// Implementations don't need to directly implement [`Iterator`]; instead there exists
38/// [`Tokens::as_iter()`] and [`Tokens::into_iter()`] methods to return an iterator that is based
39/// on the methods implemented here and keeps iterator methods in a separate namespace.
40pub trait Tokens: Sized {
41 /// The item returned from [`Tokens::next()`].
42 type Item;
43
44 /// An object which can be used to reset the token stream
45 /// to some position.
46 type Location: TokenLocation + PartialEq + core::fmt::Debug + Clone;
47
48 /// Return the next token. This is also the basis of the [`Iterator`] implementation
49 /// that's returned when you call [`Tokens::as_iter()`]. By implementing it here, we can keep
50 /// all of the methods provided by [`Iterator`] in a separate "namespace" to avoid confusion
51 /// and potential name collisions.
52 ///
53 /// # Example
54 ///
55 /// ```rust
56 /// use yap::{ Tokens, IntoTokens };
57 ///
58 /// let mut s = "abc".into_tokens();
59 ///
60 /// assert_eq!(s.next(), Some('a'));
61 /// assert_eq!(s.next(), Some('b'));
62 /// assert_eq!(s.next(), Some('c'));
63 /// assert_eq!(s.next(), None);
64 /// ```
65 fn next(&mut self) -> Option<Self::Item>;
66
67 /// Return a "location" pointer. This can be passed to [`Tokens::set_location`]
68 /// to set the tokens location back to the state at the time it was handed out.
69 /// If the [`crate::TokenLocation`] trait is in scope, you can also call the
70 /// [`crate::TokenLocation::offset()`] method on it to obtain the current offset.
71 ///
72 /// # Example
73 ///
74 /// ```rust
75 /// use yap::{ Tokens, IntoTokens, TokenLocation };
76 ///
77 /// let mut s = "abcde".into_tokens();
78 ///
79 /// let location = s.location();
80 /// assert_eq!(s.next().unwrap(), 'a');
81 /// assert_eq!(s.location().offset(), 1);
82 /// assert_eq!(s.next().unwrap(), 'b');
83 /// assert_eq!(s.location().offset(), 2);
84 ///
85 /// s.set_location(location);
86 ///
87 /// assert_eq!(s.next().unwrap(), 'a');
88 /// assert_eq!(s.location().offset(), 1);
89 /// assert_eq!(s.next().unwrap(), 'b');
90 /// assert_eq!(s.location().offset(), 2);
91 /// ```
92 fn location(&self) -> Self::Location;
93
94 /// Set the tokens to the location provided. See [`Tokens::location`].
95 fn set_location(&mut self, location: Self::Location);
96
97 /// Return true if the current cursor location matches the location given, or false
98 /// otherwise.
99 ///
100 /// # Example
101 ///
102 /// ```
103 /// use yap::{ Tokens, IntoTokens };
104 ///
105 /// let mut s = "abc".into_tokens();
106 /// let location = s.location();
107 /// assert_eq!(s.is_at_location(&location), true);
108 /// s.next();
109 /// assert_eq!(s.is_at_location(&location), false);
110 /// s.set_location(location);
111 /// assert_eq!(s.is_at_location(&location), true);
112 /// ```
113 fn is_at_location(&self, location: &Self::Location) -> bool;
114
115 /// Return an iterator over our tokens. The [`Tokens`] trait already mirrors the [`Iterator`]
116 /// interface by providing [`Tokens::Item`] and [`Tokens::next()`], but we keep the [`Iterator`]
117 /// separate to avoid collisions, and because some iterator methods don't consume tokens as you
118 /// might expect, and so must be used with care when parsing input.
119 fn as_iter(&'_ mut self) -> TokensAsIter<'_, Self> {
120 TokensAsIter { tokens: self }
121 }
122
123 /// Like [`Tokens::as_iter()`], except it consumes `self`, which can be useful in some situations.
124 fn into_iter(self) -> TokensIntoIter<Self> {
125 TokensIntoIter { tokens: self }
126 }
127
128 /// Attempt to parse the remaining tokens into the first `Out` generic using [`str::parse()`].
129 /// The second generic type may be used to buffer tokens, and can be any type that implements
130 /// `FromIterator<Self::Item> + Deref<Target = str>`.
131 ///
132 /// If the parsing fails, then no tokens are consumed.
133 ///
134 /// As an optimisation, implementations may choose not to use the provided buffer type if they have a
135 /// suitable internal buffer of their own already. This is the case for [`crate::types::StrTokens`].
136 ///
137 /// This is mostly expected to be used in conjunction with [`Tokens::take`] and [`Tokens::take_while`],
138 /// which themselves return the matching [`Tokens`].
139 ///
140 /// # Example
141 ///
142 /// ```
143 /// use yap::{ Tokens, IntoTokens };
144 ///
145 /// let mut tokens = "123abc456".into_tokens();
146 ///
147 /// let n = tokens.take(3).parse::<u8, String>().unwrap();
148 /// assert_eq!(n, 123);
149 ///
150 /// let s = tokens.take_while(|t| t.is_alphabetic()).parse::<String, String>().unwrap();
151 /// assert_eq!(s, "abc".to_string());
152 ///
153 /// // This will fail to parse; the number is out of bounds. Failure will consume
154 /// // no tokens.
155 /// assert!(tokens.parse::<u8, String>().is_err());
156 ///
157 /// // This will work; the number can fit into a u16:
158 /// let n2 = tokens.parse::<u16, String>().unwrap();
159 /// assert_eq!(n2, 456);
160 /// ```
161 fn parse<Out, Buf>(&mut self) -> Result<Out, <Out as FromStr>::Err>
162 where
163 Out: FromStr,
164 Buf: FromIterator<Self::Item> + Deref<Target = str>,
165 {
166 self.optional_err(|toks| toks.collect::<Buf>().parse::<Out>())
167 }
168
169 /// This is called when `tokens.slice(..).parse()` is called, and exists so that `Tokens`
170 /// impls have the chance to override/optimise this behaviour.
171 ///
172 /// This should never alter the location of the underlying tokens.
173 #[doc(hidden)]
174 fn parse_slice<Out, Buf>(
175 &mut self,
176 from: Self::Location,
177 to: Self::Location,
178 ) -> Result<Out, <Out as FromStr>::Err>
179 where
180 Out: FromStr,
181 Buf: FromIterator<Self::Item> + Deref<Target = str>,
182 {
183 self.slice(from, to).collect::<Buf>().parse::<Out>()
184 }
185
186 /// This is called when `tokens.take_while(..).parse()` is called, and exists so that `Tokens`
187 /// impls have the chance to override/optimise this behaviour.
188 ///
189 /// This should consume tokens on success, and consume nothing on failure.
190 #[doc(hidden)]
191 fn parse_take_while<Out, Buf, F>(&mut self, take_while: F) -> Result<Out, <Out as FromStr>::Err>
192 where
193 Out: FromStr,
194 Buf: FromIterator<Self::Item> + Deref<Target = str>,
195 F: FnMut(&Self::Item) -> bool,
196 {
197 self.optional_err(|toks| toks.take_while(take_while).collect::<Buf>().parse::<Out>())
198 }
199
200 /// This is called when `tokens.take(..).parse()` is called, and exists so that `Tokens`
201 /// impls have the chance to override/optimise this behaviour.
202 ///
203 /// This should consume tokens on success, and consume nothing on failure.
204 #[doc(hidden)]
205 fn parse_take<Out, Buf>(&mut self, n: usize) -> Result<Out, <Out as FromStr>::Err>
206 where
207 Out: FromStr,
208 Buf: FromIterator<Self::Item> + Deref<Target = str>,
209 {
210 self.optional_err(|toks| toks.take(n).collect::<Buf>().parse::<Out>())
211 }
212
213 /// Attach some context to your tokens. The returned struct, [`WithContext`], also implements
214 /// [`Tokens`], and so has can be used in much the same way. Since this consumes your tokens, it's
215 /// better suited to permanent context that you'd like throughout the parsing.
216 ///
217 /// See [`Tokens::with_context_mut`] for a version that's easier to attach temporary context with.
218 ///
219 /// # Example
220 ///
221 /// ```
222 /// use yap::{ Tokens, IntoTokens, types::WithContext };
223 ///
224 /// fn skip_digits(toks: &mut WithContext<impl Tokens<Item=char>, usize>) {
225 /// let n_skipped = toks.skip_while(|c| c.is_digit(10));
226 /// *toks.context_mut() += n_skipped;
227 /// }
228 ///
229 /// let mut tokens = "123abc456".into_tokens().with_context(0usize);
230 ///
231 /// skip_digits(&mut tokens);
232 /// tokens.skip_while(|c| c.is_alphabetic());
233 /// skip_digits(&mut tokens);
234 ///
235 /// assert_eq!(*tokens.context(), 6);
236 /// ```
237 fn with_context<C>(self, context: C) -> WithContext<Self, C> {
238 WithContext::new(self, context)
239 }
240
241 /// Unlike [`Tokens::with_context`], which consumes the tokens, this borrows them mutably, allowing it to
242 /// be used when you only have a mutable reference to tokens (which is a common function signature to use),
243 /// and making it better suited to attaching temporary contexts.
244 ///
245 /// Be aware that if you attach context in a function called recursively, the type checker may shout at you
246 /// for constructing a type like `WithContextMut<WithContextMut<WithContextMut<..>>>`. In these cases, you
247 /// can "break the cycle" by removing the original `WithContextMut` by using
248 /// [`crate::types::WithContextMut::into_parts()`] before wrapping the tokens in a new context for the recursive
249 /// call.
250 ///
251 /// # Example
252 ///
253 /// ```
254 /// use yap::{ Tokens, IntoTokens };
255 ///
256 /// fn count_digit_comma_calls(toks: &mut impl Tokens<Item=char>) -> (u8, u8) {
257 /// let mut counts = (0u8, 0u8);
258 /// toks.with_context_mut(&mut counts).sep_by(
259 /// |t| {
260 /// t.context_mut().0 += 1;
261 /// let n_skipped = t.skip_while(|c| c.is_digit(10));
262 /// if n_skipped == 0 { None } else { Some(()) }
263 /// },
264 /// |t| {
265 /// t.context_mut().1 += 1;
266 /// t.token(',')
267 /// }
268 /// ).consume();
269 /// counts
270 /// }
271 ///
272 /// let n: usize = 0;
273 /// let mut tokens = "123,4,56,1,34,1".into_tokens();
274 ///
275 /// let (digits, seps) = count_digit_comma_calls(&mut tokens);
276 ///
277 /// assert_eq!(tokens.remaining().len(), 0);
278 /// // digits parsed 6 times:
279 /// assert_eq!(digits, 6);
280 /// // Attempted to parse seps 6 times; failure on last ends it:
281 /// assert_eq!(seps, 6);
282 /// ```
283 fn with_context_mut<C>(&mut self, context: C) -> WithContextMut<&mut Self, C> {
284 WithContextMut::new(self, context)
285 }
286
287 /// Return a slice of tokens starting at the `to` location provided and ending just prior to
288 /// the `from` location provided (ie equivalent to the range `to..from`).
289 ///
290 /// The slice returned from implements [`Tokens`], so you can use the full range
291 /// of parsing functions on it.
292 ///
293 /// **Note:** the slice returned from this prevents the original tokens from being used until
294 /// it's dropped, and resets the original tokens to their current location on `Drop`. if you
295 /// [`core::mem::forget`] it, the original token location will equal whatever the slice location
296 /// was when it was forgotten.
297 ///
298 /// # Example
299 ///
300 /// ```rust
301 /// use yap::{ Tokens, IntoTokens };
302 ///
303 /// let mut s = "abcdefghijklmnop".into_tokens();
304 ///
305 /// (0..5).for_each(|_| { s.next(); });
306 /// let from = s.location();
307 /// (0..5).for_each(|_| { s.next(); });
308 /// let to = s.location();
309 ///
310 /// assert_eq!(s.next(), Some('k'));
311 /// assert_eq!(s.next(), Some('l'));
312 ///
313 /// // Iterating the from..to range given:
314 /// let vals: String = s.slice(from.clone(), to.clone()).collect();
315 /// assert_eq!(&*vals, "fghij");
316 ///
317 /// // After the above is dropped, we can continue
318 /// // from where we left off:
319 /// assert_eq!(s.next(), Some('m'));
320 /// assert_eq!(s.next(), Some('n'));
321 ///
322 /// // We can iterate this range again as we please:
323 /// let vals: String = s.slice(from, to).collect();
324 /// assert_eq!(&*vals, "fghij");
325 ///
326 /// // And the original remains unaffected..
327 /// assert_eq!(s.next(), Some('o'));
328 /// assert_eq!(s.next(), Some('p'));
329 /// ```
330 fn slice(&'_ mut self, from: Self::Location, to: Self::Location) -> Slice<'_, Self> {
331 Slice::new(self, self.location(), from, to)
332 }
333
334 /// Return the current offset into the tokens that we've parsed up to so far.
335 /// The exact meaning of this can vary by implementation; when parsing slices, it
336 /// is index of the slice item we've consumed up to, and when
337 /// parsing `&str`'s it is the number of bytes (not characters) consumed so far.
338 ///
339 /// # Example
340 ///
341 /// ```
342 /// use yap::{ Tokens, IntoTokens };
343 ///
344 /// let mut s = "abc".into_tokens();
345 /// assert_eq!(s.offset(), 0);
346 /// s.next();
347 /// assert_eq!(s.offset(), 1);
348 /// s.next();
349 /// assert_eq!(s.offset(), 2);
350 /// ```
351 fn offset(&self) -> usize {
352 self.location().offset()
353 }
354
355 /// Return the next item in the input without consuming it.
356 ///
357 /// Prefer this to using the `peekable` iterator method, which consumes
358 /// the tokens, and internally keeps hold of the peeked state itself.
359 ///
360 /// # Example
361 ///
362 /// ```
363 /// use yap::{ Tokens, IntoTokens };
364 ///
365 /// let mut s = "abc".into_tokens();
366 /// assert_eq!(s.peek(), Some('a'));
367 /// assert_eq!(s.peek(), Some('a'));
368 /// ```
369 fn peek(&mut self) -> Option<Self::Item> {
370 let location = self.location();
371 let item = self.next();
372 self.set_location(location);
373 item
374 }
375
376 /// Expect a specific token to be next. If the token is not found, the iterator is not
377 /// advanced.
378 ///
379 /// # Example
380 ///
381 /// ```
382 /// use yap::{ Tokens, IntoTokens };
383 ///
384 /// let mut s = "abc".into_tokens();
385 /// assert_eq!(s.token(&'a'), true);
386 /// assert_eq!(s.token(&'b'), true);
387 /// assert_eq!(s.token('z'), false);
388 /// assert_eq!(s.token('y'), false);
389 /// assert_eq!(s.token('c'), true);
390 /// ```
391 fn token<I>(&mut self, t: I) -> bool
392 where
393 Self::Item: PartialEq,
394 I: Borrow<Self::Item>,
395 {
396 let location = self.location();
397 match self.next() {
398 Some(item) if &item == t.borrow() => true,
399 _ => {
400 self.set_location(location);
401 false
402 }
403 }
404 }
405
406 /// Expect a specific set of tokens to be next. If the tokens are not found, the iterator is not
407 /// advanced. Anything that implements `IntoIterator` with an `Item` type that can be borrowed to
408 /// produce `&Item` can be provided as an input to this.
409 ///
410 /// # Example
411 ///
412 /// ```
413 /// use yap::{ Tokens, IntoTokens };
414 ///
415 /// let mut s = "abcdef".into_tokens();
416 ///
417 /// assert_eq!(s.tokens("abc".chars()), true);
418 /// assert_eq!(s.remaining(), "def");
419 ///
420 /// assert_eq!(s.tokens("de".chars()), true);
421 /// assert_eq!(s.remaining(), "f");
422 /// ```
423 fn tokens<It>(&mut self, ts: It) -> bool
424 where
425 Self::Item: PartialEq,
426 It: IntoIterator,
427 It::Item: Borrow<Self::Item>,
428 {
429 let location = self.location();
430
431 // We don't `.zip()` here because we need to spot and handle the
432 // case where we run out of self tokens before `ts` runs out, and reset
433 // /return false in that situation.
434 let ts_iter = ts.into_iter();
435 for expected in ts_iter {
436 match self.next() {
437 Some(actual) => {
438 // We have a token; does it equal the expected one?
439 if &actual != expected.borrow() {
440 self.set_location(location);
441 return false;
442 }
443 }
444 None => {
445 // We ran out of tokens in self, so no match.
446 self.set_location(location);
447 return false;
448 }
449 }
450 }
451 true
452 }
453
454 /// Return the first token that matches the tokens provided, or None if none of them
455 /// match.
456 ///
457 /// # Example
458 ///
459 /// ```
460 /// use yap::{ Tokens, IntoTokens };
461 ///
462 /// let mut s = "abcdef".into_tokens();
463 ///
464 /// assert_eq!(s.one_of_tokens("abc".chars()), Some('a'));
465 /// assert_eq!(s.one_of_tokens("abc".chars()), Some('b'));
466 /// assert_eq!(s.one_of_tokens("abc".chars()), Some('c'));
467 /// assert_eq!(s.one_of_tokens("abc".chars()), None);
468 /// assert_eq!(s.remaining(), "def");
469 /// ```
470 fn one_of_tokens<It>(&mut self, ts: It) -> Option<Self::Item>
471 where
472 Self::Item: PartialEq,
473 It: IntoIterator,
474 It::Item: Borrow<Self::Item>,
475 {
476 for expected in ts.into_iter() {
477 let location = self.location();
478 match self.next() {
479 Some(token) if &token == expected.borrow() => return Some(token),
480 _ => {
481 self.set_location(location);
482 }
483 }
484 }
485 None
486 }
487
488 /// Return a [`Tokens`] impl that will take the next `n` tokens from the input (ending early
489 /// if the input runs early).
490 ///
491 /// # Example
492 ///
493 /// ```
494 /// use yap::{ Tokens, IntoTokens };
495 ///
496 /// let mut s = "12345abc".into_tokens();
497 /// let digits: String = s.take(3).collect();
498 /// assert_eq!(&*digits, "123");
499 /// assert_eq!(s.remaining(), "45abc");
500 /// ```
501 fn take(&'_ mut self, n: usize) -> Take<'_, Self> {
502 Take::new(self, n)
503 }
504
505 /// Return a [`Tokens`] impl that will consume tokens until the provided function returns false.
506 ///
507 /// # Example
508 ///
509 /// ```
510 /// use yap::{ Tokens, IntoTokens };
511 ///
512 /// let mut s = "12345abc".into_tokens();
513 /// let digits: String = s.take_while(|c| c.is_numeric()).collect();
514 /// assert_eq!(&*digits, "12345");
515 /// assert_eq!(s.remaining(), "abc");
516 /// ```
517 ///
518 /// This exists primarily because [`Iterator::take_while()`] will consume the first token that
519 /// does not match the predicate, which is often not what we'd want. The above example using
520 /// [`Iterator::take_while()`] would look like:
521 ///
522 /// ```rust
523 /// use yap::{ Tokens, IntoTokens };
524 ///
525 /// let mut s = "12345abc".into_tokens();
526 /// let digits: String = s.as_iter().take_while(|c| c.is_numeric()).collect();
527 /// assert_eq!(&*digits, "12345");
528 ///
529 /// // Note that `Iterator::take_while` consumed the "a" in order to test it,
530 /// // whereas `Tokens::take_while` did not:
531 /// assert_eq!(s.remaining(), "bc");
532 /// ```
533 fn take_while<F>(&'_ mut self, f: F) -> TakeWhile<'_, Self, F>
534 where
535 F: FnMut(&Self::Item) -> bool,
536 {
537 TakeWhile::new(self, f)
538 }
539
540 /// Iterate over the tokens until the provided function returns false on one. Only consume the tokens
541 /// that the function returned true for, returning the number of tokens that were consumed/skipped.
542 /// Equivalent to `toks.take_while(f).count()`.
543 ///
544 /// # Example
545 ///
546 /// ```
547 /// use yap::{ Tokens, IntoTokens };
548 ///
549 /// let mut s = "12345abc".into_tokens();
550 /// let n_skipped = s.skip_while(|c| c.is_numeric());
551 ///
552 /// assert_eq!(n_skipped, 5);
553 /// assert_eq!(s.remaining(), "abc");
554 /// ```
555 fn skip_while<F>(&mut self, f: F) -> usize
556 where
557 F: FnMut(&Self::Item) -> bool,
558 {
559 self.take_while(f).as_iter().count()
560 }
561
562 /// Returns a [`Tokens`] impl that runs the provided parser again and again, returning
563 /// an output from it each time until it returns [`None`].
564 ///
565 /// # Example
566 ///
567 /// ```rust
568 /// use yap::{ Tokens, IntoTokens };
569 ///
570 /// fn parse_digit_pair(tokens: &mut impl Tokens<Item=char>) -> Option<u32> {
571 /// let d1 = tokens.next()?;
572 /// let d2 = tokens.next()?;
573 /// // Return the result of adding the 2 digits we saw:
574 /// Some(d1.to_digit(10)? + d2.to_digit(10)?)
575 /// }
576 ///
577 /// let mut s = "12345abcde".into_tokens();
578 /// let digits: Vec<u32> = s.many(|t| parse_digit_pair(t)).collect();
579 ///
580 /// assert_eq!(digits, vec![3, 7]);
581 /// assert_eq!(s.remaining(), "5abcde");
582 /// ```
583 fn many<F, Output>(&mut self, parser: F) -> Many<Self, F>
584 where
585 F: FnMut(&mut Self) -> Option<Output>,
586 {
587 Many::new(self, parser)
588 }
589
590 /// Returns a [`Tokens`] impl that runs the provided parser again and again, returning
591 /// an output from it each time until it returns [`None`]. If the parser returns an error,
592 /// no tokens will be consumed and the error will be returned as the final iteration.
593 ///
594 /// # Example
595 ///
596 /// ```rust
597 /// use yap::{ Tokens, IntoTokens };
598 ///
599 /// #[derive(Debug, PartialEq)]
600 /// enum Err { NotEnoughTokens, NotADigit(char) }
601 /// fn parse_digit_pair(tokens: &mut impl Tokens<Item=char>) -> Result<u32, Err> {
602 /// let n1 = tokens.next()
603 /// .ok_or(Err::NotEnoughTokens)
604 /// .and_then(|c| c.to_digit(10).ok_or(Err::NotADigit(c)))?;
605 /// let n2 = tokens.next()
606 /// .ok_or(Err::NotEnoughTokens)
607 /// .and_then(|c| c.to_digit(10).ok_or(Err::NotADigit(c)))?;
608 /// Ok(n1 + n2)
609 /// }
610 ///
611 /// let mut s = "12345abcde".into_tokens();
612 /// let mut digits_iter = s.many_err(|t| parse_digit_pair(t));
613 ///
614 /// assert_eq!(digits_iter.next(), Some(Ok(3)));
615 /// assert_eq!(digits_iter.next(), Some(Ok(7)));
616 /// assert_eq!(digits_iter.next(), Some(Err(Err::NotADigit('a'))));
617 /// assert_eq!(digits_iter.next(), None);
618 /// assert_eq!(s.remaining(), "5abcde");
619 /// ```
620 fn many_err<F, Output, E>(&'_ mut self, parser: F) -> ManyErr<'_, Self, F>
621 where
622 F: FnMut(&mut Self) -> Result<Output, E>,
623 {
624 ManyErr::new(self, parser)
625 }
626
627 /// Ignore 0 or more instances of some parser.
628 ///
629 /// # Example
630 ///
631 /// ```rust
632 /// use yap::{ Tokens, IntoTokens };
633 ///
634 /// struct ABC;
635 /// fn parse_abc(tokens: &mut impl Tokens<Item=char>) -> Option<ABC> {
636 /// let a = tokens.next()?;
637 /// let b = tokens.next()?;
638 /// let c = tokens.next()?;
639 /// if a == 'a' && b == 'b' && c == 'c' {
640 /// Some(ABC)
641 /// } else {
642 /// None
643 /// }
644 /// }
645 ///
646 /// let mut s = "abcabcababab".into_tokens();
647 /// s.skip_many(|t| parse_abc(t).is_some());
648 ///
649 /// assert_eq!(s.remaining(), "ababab");
650 /// ```
651 fn skip_many<F>(&mut self, mut parser: F) -> usize
652 where
653 F: FnMut(&mut Self) -> bool,
654 {
655 self.many(|t| parser(t).then_some(())).as_iter().count()
656 }
657
658 /// Ignore 1 or more instances of some parser. If the provided parser
659 /// fails immediately, return the error that it produced.
660 ///
661 /// # Example
662 ///
663 /// ```rust
664 /// use yap::{ Tokens, IntoTokens };
665 ///
666 /// struct ABC;
667 /// fn parse_abc(tokens: &mut impl Tokens<Item=char>) -> Option<ABC> {
668 /// let a = tokens.next()?;
669 /// let b = tokens.next()?;
670 /// let c = tokens.next()?;
671 /// if a == 'a' && b == 'b' && c == 'c' {
672 /// Some(ABC)
673 /// } else {
674 /// None
675 /// }
676 /// }
677 ///
678 /// let mut s = "abcabcabcxyz".into_tokens();
679 /// let skipped = s.skip_many1(|t| parse_abc(t).ok_or("aaah"));
680 ///
681 /// assert_eq!(skipped, Ok(3));
682 /// assert_eq!(s.remaining(), "xyz");
683 ///
684 /// let mut s = "ababababcabc".into_tokens();
685 /// let skipped = s.skip_many1(|t| parse_abc(t).ok_or("aaah"));
686 ///
687 /// assert_eq!(skipped, Err("aaah"));
688 /// assert_eq!(s.remaining(), "ababababcabc");
689 /// ```
690 fn skip_many1<F, E, Ignored>(&mut self, parser: F) -> Result<usize, E>
691 where
692 F: FnMut(&mut Self) -> Result<Ignored, E>,
693 {
694 let mut toks = self.many_err(parser);
695 // Return error if immediate fail:
696 if let Some(Err(e)) = toks.next() {
697 return Err(e);
698 }
699 // Else just consume whatever we can and count it all up.
700 // Note: the last iteration of `many_err` will return an Error
701 // and not a value, so where we'd otherwise `+1` this count to
702 // account for the `iter.next()` above, we don't have to.
703 let n_skipped = toks.as_iter().count();
704 Ok(n_skipped)
705 }
706
707 /// Return a [`Tokens`] impl that parses anything matching the first `parser` function,
708 /// and expects to parse something matching the second `separator` function between each
709 /// of these.
710 ///
711 /// # Example
712 ///
713 /// ```
714 /// use yap::{ Tokens, IntoTokens };
715 ///
716 /// fn parse_digit(tokens: &mut impl Tokens<Item=char>) -> Option<u32> {
717 /// let c = tokens.next()?;
718 /// c.to_digit(10)
719 /// }
720 ///
721 /// let mut s = "1,2,3,4,abc".into_tokens();
722 /// let digits: Vec<u32> = s.sep_by(|t| parse_digit(t), |t| t.token(',')).collect();
723 /// assert_eq!(digits, vec![1,2,3,4]);
724 /// assert_eq!(s.remaining(), ",abc");
725 /// ```
726 fn sep_by<F, S, Output>(&'_ mut self, parser: F, separator: S) -> SepBy<'_, Self, F, S>
727 where
728 F: FnMut(&mut Self) -> Option<Output>,
729 S: FnMut(&mut Self) -> bool,
730 {
731 SepBy::new(self, parser, separator)
732 }
733
734 /// Return a [`Tokens`] impl that parses anything matching the `parser` function, and expects
735 /// to parse something matching the `separator` function between each one. Unlike [`Tokens::sep_by`],
736 /// this accepts parsers that return `Result`s, and returns the result on each iteration. Once
737 /// an error is hit, `None` is returned thereafter.
738 ///
739 /// # Example
740 ///
741 /// ```
742 /// use yap::{ Tokens, IntoTokens };
743 ///
744 /// #[derive(Debug, PartialEq)]
745 /// enum Err { NoMoreTokens, NotADigit(char) }
746 ///
747 /// fn parse_digit(tokens: &mut impl Tokens<Item=char>) -> Result<u32, Err> {
748 /// let c = tokens.next().ok_or(Err::NoMoreTokens)?;
749 /// c.to_digit(10).ok_or(Err::NotADigit(c))
750 /// }
751 ///
752 /// let mut s = "1,2,a,1,2,3".into_tokens();
753 /// let mut digits_iter = s.sep_by_err(|t| parse_digit(t), |t| t.token(','));
754 /// assert_eq!(digits_iter.next(), Some(Ok(1)));
755 /// assert_eq!(digits_iter.next(), Some(Ok(2)));
756 /// assert_eq!(digits_iter.next(), Some(Err(Err::NotADigit('a'))));
757 /// assert_eq!(digits_iter.next(), None);
758 /// assert_eq!(s.remaining(), ",a,1,2,3");
759 /// ```
760 fn sep_by_err<F, S, E, Output>(
761 &'_ mut self,
762 parser: F,
763 separator: S,
764 ) -> SepByErr<'_, Self, F, S>
765 where
766 F: FnMut(&mut Self) -> Result<Output, E>,
767 S: FnMut(&mut Self) -> bool,
768 {
769 SepByErr::new(self, parser, separator)
770 }
771
772 /// Returns a [`Tokens`] impl that parses anything matching the `parser` function,
773 /// and expects to parse something matching the `separator` function between each one.
774 /// The [`Tokens`] impl hands back the output from both the `parser` and `separator`
775 /// function, which means that they are both expected to return the same type.
776 ///
777 /// # Example
778 ///
779 /// ```
780 /// use yap::{ Tokens, IntoTokens };
781 ///
782 /// #[derive(PartialEq,Debug)]
783 /// enum Op { Plus, Minus, Divide }
784 /// #[derive(PartialEq,Debug)]
785 /// enum OpOrDigit { Op(Op), Digit(u32) }
786 ///
787 /// fn parse_op(tokens: &mut impl Tokens<Item=char>) -> Option<Op> {
788 /// match tokens.next()? {
789 /// '-' => Some(Op::Minus),
790 /// '+' => Some(Op::Plus),
791 /// '/' => Some(Op::Divide),
792 /// _ => None
793 /// }
794 /// }
795 ///
796 /// fn parse_digit(tokens: &mut impl Tokens<Item=char>) -> Option<u32> {
797 /// let c = tokens.next()?;
798 /// c.to_digit(10)
799 /// }
800 ///
801 /// let mut s = "1+2/3-4+abc".into_tokens();
802 /// let output: Vec<_> = s.sep_by_all(
803 /// |t| parse_digit(t).map(OpOrDigit::Digit),
804 /// |t| parse_op(t).map(OpOrDigit::Op)
805 /// ).collect();
806 ///
807 /// assert_eq!(output, vec![
808 /// OpOrDigit::Digit(1),
809 /// OpOrDigit::Op(Op::Plus),
810 /// OpOrDigit::Digit(2),
811 /// OpOrDigit::Op(Op::Divide),
812 /// OpOrDigit::Digit(3),
813 /// OpOrDigit::Op(Op::Minus),
814 /// OpOrDigit::Digit(4),
815 /// ]);
816 /// assert_eq!(s.remaining(), "+abc");
817 /// ```
818 fn sep_by_all<F, S, Output>(
819 &'_ mut self,
820 parser: F,
821 separator: S,
822 ) -> SepByAll<'_, Self, F, S, Output>
823 where
824 F: FnMut(&mut Self) -> Option<Output>,
825 S: FnMut(&mut Self) -> Option<Output>,
826 {
827 SepByAll::new(self, parser, separator)
828 }
829
830 /// Similar to [`Tokens::sep_by_all`], except that the [`Tokens`] impl returned also
831 /// hands back the first error encountered when attempting to run our `parser`.
832 ///
833 /// # Example
834 ///
835 /// ```
836 /// use yap::{ Tokens, IntoTokens };
837 ///
838 /// #[derive(PartialEq,Debug)]
839 /// enum Op { Plus, Minus, Divide }
840 /// #[derive(PartialEq,Debug)]
841 /// enum OpOrDigit { Op(Op), Digit(u32) }
842 /// #[derive(Debug, PartialEq)]
843 /// enum Err { NoMoreTokens, NotADigit(char) }
844 ///
845 /// fn parse_op(tokens: &mut impl Tokens<Item=char>) -> Option<Op> {
846 /// match tokens.next()? {
847 /// '-' => Some(Op::Minus),
848 /// '+' => Some(Op::Plus),
849 /// '/' => Some(Op::Divide),
850 /// _ => None
851 /// }
852 /// }
853 ///
854 /// fn parse_digit(tokens: &mut impl Tokens<Item=char>) -> Result<u32, Err> {
855 /// let c = tokens.next().ok_or(Err::NoMoreTokens)?;
856 /// c.to_digit(10).ok_or(Err::NotADigit(c))
857 /// }
858 ///
859 /// let mut s = "1+2/3-4+abc".into_tokens();
860 /// let output: Vec<_> = s.sep_by_all_err(
861 /// |t| parse_digit(t).map(OpOrDigit::Digit),
862 /// |t| parse_op(t).map(OpOrDigit::Op)
863 /// ).collect();
864 ///
865 /// assert_eq!(output, vec![
866 /// Ok(OpOrDigit::Digit(1)),
867 /// Ok(OpOrDigit::Op(Op::Plus)),
868 /// Ok(OpOrDigit::Digit(2)),
869 /// Ok(OpOrDigit::Op(Op::Divide)),
870 /// Ok(OpOrDigit::Digit(3)),
871 /// Ok(OpOrDigit::Op(Op::Minus)),
872 /// Ok(OpOrDigit::Digit(4)),
873 /// Err(Err::NotADigit('a'))
874 /// ]);
875 /// assert_eq!(s.remaining(), "+abc");
876 /// ```
877 fn sep_by_all_err<F, S, Output, E>(
878 &'_ mut self,
879 parser: F,
880 separator: S,
881 ) -> SepByAllErr<'_, Self, F, S, Output>
882 where
883 F: FnMut(&mut Self) -> Result<Output, E>,
884 S: FnMut(&mut Self) -> Option<Output>,
885 {
886 SepByAllErr::new(self, parser, separator)
887 }
888
889 /// Parse some tokens that are optionally surrounded by the result of a `surrounding` parser.
890 ///
891 /// # Example
892 ///
893 /// ```
894 /// use yap::{ Tokens, IntoTokens };
895 ///
896 /// let mut s = " hello ".into_tokens();
897 ///
898 /// let hello: String = s.surrounded_by(
899 /// |t| t.take_while(|c| c.is_ascii_alphabetic()).collect(),
900 /// |t| { t.skip_while(|c| c.is_ascii_whitespace()); }
901 /// );
902 ///
903 /// assert_eq!(&*hello, "hello");
904 /// assert_eq!(s.remaining(), "");
905 /// ```
906 fn surrounded_by<F, S, Output>(&mut self, parser: F, mut surrounding: S) -> Output
907 where
908 F: FnOnce(&mut Self) -> Output,
909 S: FnMut(&mut Self),
910 {
911 surrounding(self);
912 let res = parser(self);
913 surrounding(self);
914 res
915 }
916
917 /// Attempt to parse some output from the tokens. Returning `None`
918 /// or `false` signifies that no match was found, and no tokens will
919 /// be consumed. Otherwise, we'll return the match and consume the tokens.
920 ///
921 /// # Example
922 ///
923 /// ```
924 /// use yap::{ Tokens, IntoTokens };
925 ///
926 /// let mut s = "foobar".into_tokens();
927 ///
928 /// let res = s.optional(|s| {
929 /// let a = s.next();
930 /// let b = s.next();
931 /// if a == b {
932 /// Some("yay")
933 /// } else {
934 /// None
935 /// }
936 /// });
937 ///
938 /// // nothing consumed since None returned from fn
939 /// assert_eq!(s.remaining(), "foobar");
940 /// assert_eq!(res, None);
941 ///
942 /// let res = s.optional(|s| {
943 /// let a = s.next()?;
944 /// let b = s.next()?;
945 /// Some((a, b))
946 /// });
947 ///
948 /// // 2 chars consumed since Some returned from fn
949 /// assert_eq!(s.remaining(), "obar");
950 /// assert_eq!(res, Some(('f', 'o')));
951 /// ```
952 fn optional<F, Output>(&mut self, f: F) -> Output
953 where
954 F: FnOnce(&mut Self) -> Output,
955 Output: crate::one_of::IsMatch,
956 {
957 let location = self.location();
958 if let Some(output) = f(self).into_match() {
959 output
960 } else {
961 self.set_location(location);
962 crate::one_of::IsMatch::match_failure()
963 }
964 }
965
966 /// Attempt to parse some output from the tokens, returning a `Result`.
967 /// If the `Result` returned is `Err`, no tokens will be consumed.
968 ///
969 /// # Example
970 ///
971 /// ```
972 /// use yap::{ Tokens, IntoTokens };
973 ///
974 /// let mut s = "foobar".into_tokens();
975 ///
976 /// let res = s.optional_err(|s| {
977 /// let a = s.next();
978 /// let b = s.next();
979 /// if a == b {
980 /// Ok("yay")
981 /// } else {
982 /// Err("a and b don't match!")
983 /// }
984 /// });
985 ///
986 /// // nothing consumed since Err returned from fn
987 /// assert_eq!(s.remaining(), "foobar");
988 /// assert!(res.is_err());
989 ///
990 /// let res = s.optional_err(|s| {
991 /// let a = s.next();
992 /// let b = s.next();
993 /// if a != b {
994 /// Ok((a, b))
995 /// } else {
996 /// Err("a and b match!")
997 /// }
998 /// });
999 ///
1000 /// // 2 chars consumed since Ok returned from fn
1001 /// assert_eq!(s.remaining(), "obar");
1002 /// assert_eq!(res, Ok((Some('f'), Some('o'))));
1003 /// ```
1004 fn optional_err<F, Output, Error>(&mut self, f: F) -> Result<Output, Error>
1005 where
1006 F: FnOnce(&mut Self) -> Result<Output, Error>,
1007 {
1008 let location = self.location();
1009 match f(self) {
1010 Ok(output) => Ok(output),
1011 Err(err) => {
1012 self.set_location(location);
1013 Err(err)
1014 }
1015 }
1016 }
1017
1018 /// Checks next input is [`None`] and, if true, consumes the `None`.
1019 ///
1020 /// # Example
1021 ///
1022 /// ```
1023 /// use yap::Tokens;
1024 /// use yap::types::IterTokens;
1025 /// use core::iter;
1026 ///
1027 /// // This will always return None; eof will consume it.
1028 /// let mut toks = IterTokens::new(iter::empty::<char>());
1029 ///
1030 /// assert_eq!(toks.eof(), true);
1031 /// assert_eq!(toks.offset(), 1);
1032 ///
1033 /// assert_eq!(toks.eof(), true);
1034 /// assert_eq!(toks.offset(), 2);
1035 ///
1036 /// // This will return a char; eof won't consume anything.
1037 /// let mut toks = IterTokens::new(iter::once('a'));
1038 ///
1039 /// assert_eq!(toks.eof(), false);
1040 /// assert_eq!(toks.offset(), 0);
1041 ///
1042 /// assert_eq!(toks.eof(), false);
1043 /// assert_eq!(toks.offset(), 0);
1044 /// ```
1045 fn eof(&mut self) -> bool {
1046 self.optional(|t| t.next().is_none().then_some(()))
1047 .is_some()
1048 }
1049
1050 /// Consume all remaining tokens. This is expected to be used in conjunction
1051 /// with combinators like[`Tokens::take`] and [`Tokens::take_while`]. This is
1052 /// just a shorthand for `toks.as_iter().for_each(drop)`.
1053 ///
1054 /// # Example
1055 ///
1056 /// ```
1057 /// use yap::{Tokens, IntoTokens};
1058 ///
1059 /// let mut toks = "abc123def".into_tokens();
1060 ///
1061 /// // Take won't do anything unless it's consumed:
1062 /// toks.take(3);
1063 /// assert_eq!(toks.remaining(), "abc123def");
1064 ///
1065 /// // This is the same as `toks.take(3).as_iter().for_each(drop);`
1066 /// toks.take(3).consume();
1067 /// assert_eq!(toks.remaining(), "123def");
1068 ///
1069 /// toks.take_while(|t| t.is_numeric()).consume();
1070 /// assert_eq!(toks.remaining(), "def");
1071 /// ```
1072 fn consume(&mut self) {
1073 self.as_iter().for_each(drop)
1074 }
1075
1076 /// Collect up all of the tokens into something that implements
1077 /// [`FromIterator`]. If you'd like to call `str::parse` on the
1078 /// subsequent collection, then prefer [`Tokens::parse`], which can
1079 /// be more optimal in some cases.
1080 ///
1081 /// This is just a shorthand for calling `toks.as_iter().collect()`.
1082 fn collect<B: FromIterator<Self::Item>>(&mut self) -> B {
1083 self.as_iter().collect()
1084 }
1085}
1086
1087/// Calling [`Tokens::location()`] returns an object that implements this trait.
1088pub trait TokenLocation {
1089 /// Return the current offset into the tokens at the point at which this object
1090 /// was created. [`Tokens::offset()`] is simply a shorthand for calling this method
1091 /// at the current location.
1092 ///
1093 /// # Example
1094 ///
1095 /// ```
1096 /// use yap::{ Tokens, IntoTokens, TokenLocation };
1097 ///
1098 /// let mut s = "abc".into_tokens();
1099 /// assert_eq!(s.location().offset(), 0);
1100 /// s.next();
1101 /// assert_eq!(s.location().offset(), 1);
1102 /// s.next();
1103 /// assert_eq!(s.location().offset(), 2);
1104 /// ```
1105 fn offset(&self) -> usize;
1106}
1107
1108/// A trait that is implemented by anything which can be converted into an
1109/// object implementing the [`Tokens`] trait.
1110pub trait IntoTokens<Item> {
1111 /// The type that will be used to implement the [`Tokens`] interface.
1112 type Tokens: Tokens<Item = Item>;
1113 /// Convert self into a type which implements the [`Tokens`] interface.
1114 fn into_tokens(self) -> Self::Tokens;
1115}
1116
1117/// This is returned from [`Tokens::as_iter()`], and exposes the standard iterator
1118/// interface and methods on our tokens.
1119pub struct TokensAsIter<'a, T> {
1120 tokens: &'a mut T,
1121}
1122impl<'a, T: Tokens> Iterator for TokensAsIter<'a, T> {
1123 type Item = T::Item;
1124 fn next(&mut self) -> Option<Self::Item> {
1125 self.tokens.next()
1126 }
1127}
1128
1129/// This is returned from [`Tokens::into_iter()`], and exposes the standard iterator
1130/// interface and methods on our tokens.
1131pub struct TokensIntoIter<T> {
1132 tokens: T,
1133}
1134impl<T: Tokens> Iterator for TokensIntoIter<T> {
1135 type Item = T::Item;
1136 fn next(&mut self) -> Option<Self::Item> {
1137 self.tokens.next()
1138 }
1139}
1140
1141#[cfg(all(test, feature = "std"))]
1142mod test {
1143
1144 use crate::types::IterTokens;
1145
1146 use super::*;
1147
1148 #[derive(Debug, PartialEq)]
1149 struct AB;
1150
1151 // A simple parser that looks for "ab" in an input token stream.
1152 // Notably, it doesn't try to rewind on failure. We expect the `many`
1153 // combinators to take care of that sort of thing for us as needed.
1154 fn parse_ab(t: &mut impl Tokens<Item = char>) -> Option<AB> {
1155 // match any sequence "ab".
1156 let a = t.next()?;
1157 let b = t.next()?;
1158 if a == 'a' && b == 'b' {
1159 Some(AB)
1160 } else {
1161 None
1162 }
1163 }
1164
1165 // Similar to the above, except it reports a more specific reason for
1166 // failure.
1167 fn parse_ab_err(t: &mut impl Tokens<Item = char>) -> Result<AB, ABErr> {
1168 // match any sequence "ab".
1169 let a = t.next().ok_or(ABErr::NotEnoughTokens)?;
1170 let b = t.next().ok_or(ABErr::NotEnoughTokens)?;
1171
1172 if a != 'a' {
1173 Err(ABErr::IsNotA)
1174 } else if b != 'b' {
1175 Err(ABErr::IsNotB)
1176 } else {
1177 Ok(AB)
1178 }
1179 }
1180
1181 #[derive(Debug, PartialEq)]
1182 enum ABErr {
1183 NotEnoughTokens,
1184 IsNotA,
1185 IsNotB,
1186 }
1187
1188 #[test]
1189 fn test_tokens_fails_if_eof() {
1190 let mut t = "hi".into_tokens();
1191 assert!(!t.tokens("hip".chars()));
1192 }
1193
1194 #[test]
1195 #[allow(clippy::needless_collect)]
1196 fn test_many() {
1197 // No input:
1198 let mut t = "".into_tokens();
1199 let abs: Vec<_> = t.many(parse_ab).collect();
1200 let rest: Vec<char> = t.collect();
1201
1202 assert_eq!(abs.len(), 0);
1203 assert_eq!(rest, vec![]);
1204
1205 // Invalid input after half is consumed:
1206 let mut t = "acabab".into_tokens();
1207 let abs: Vec<_> = t.many(parse_ab).collect();
1208 let rest: Vec<char> = t.collect();
1209
1210 assert_eq!(abs.len(), 0);
1211 assert_eq!(rest, vec!['a', 'c', 'a', 'b', 'a', 'b']);
1212
1213 // 3 valid and then 1 half-invalid:
1214 let mut t = "abababaa".into_tokens();
1215 let abs: Vec<_> = t.many(parse_ab).collect();
1216 let rest: Vec<char> = t.collect();
1217
1218 assert_eq!(abs.len(), 3);
1219 assert_eq!(rest, vec!['a', 'a']);
1220
1221 // End of tokens before can parse the fourth:
1222 let mut t = "abababa".into_tokens();
1223 let abs: Vec<_> = t.many(parse_ab).collect();
1224 let rest: Vec<char> = t.collect();
1225
1226 assert_eq!(abs.len(), 3);
1227 assert_eq!(rest, vec!['a']);
1228 }
1229
1230 #[test]
1231 #[allow(clippy::needless_collect)]
1232 fn test_many_err() {
1233 // No input:
1234 let mut t = "".into_tokens();
1235 let abs: Vec<_> = t.many_err(parse_ab_err).collect();
1236 let rest: Vec<char> = t.collect();
1237
1238 assert_eq!(abs, vec![Err(ABErr::NotEnoughTokens)]);
1239 assert_eq!(rest, vec![]);
1240
1241 // Invalid input immediately:
1242 let mut t = "ccabab".into_tokens();
1243 let abs: Vec<_> = t.many_err(parse_ab_err).collect();
1244 let rest: Vec<char> = t.collect();
1245
1246 assert_eq!(abs, vec![Err(ABErr::IsNotA)]);
1247 assert_eq!(rest, vec!['c', 'c', 'a', 'b', 'a', 'b']);
1248
1249 // Invalid input after half is consumed:
1250 let mut t = "acabab".into_tokens();
1251 let abs: Vec<_> = t.many_err(parse_ab_err).collect();
1252 let rest: Vec<char> = t.collect();
1253
1254 assert_eq!(abs, vec![Err(ABErr::IsNotB)]);
1255 assert_eq!(rest, vec!['a', 'c', 'a', 'b', 'a', 'b']);
1256
1257 // 3 valid and then 1 half-invalid:
1258 let mut t = "abababaa".into_tokens();
1259 let abs: Vec<_> = t.many_err(parse_ab_err).collect();
1260 let rest: Vec<char> = t.collect();
1261
1262 assert_eq!(abs, vec![Ok(AB), Ok(AB), Ok(AB), Err(ABErr::IsNotB)]);
1263 assert_eq!(rest, vec!['a', 'a']);
1264
1265 // End of tokens before can parse the fourth:
1266 let mut t = "abababa".into_tokens();
1267 let abs: Vec<_> = t.many_err(parse_ab_err).collect();
1268 let rest: Vec<char> = t.collect();
1269
1270 assert_eq!(
1271 abs,
1272 vec![Ok(AB), Ok(AB), Ok(AB), Err(ABErr::NotEnoughTokens)]
1273 );
1274 assert_eq!(rest, vec!['a']);
1275 }
1276
1277 #[test]
1278 fn test_skip_many() {
1279 let mut t = "".into_tokens();
1280 let n_skipped = t.skip_many(|t| parse_ab(t).is_some());
1281 let rest: Vec<char> = t.collect();
1282 assert_eq!(n_skipped, 0);
1283 assert_eq!(rest, vec![]);
1284
1285 let mut t = "acabab".into_tokens();
1286 let n_skipped = t.skip_many(|t| parse_ab(t).is_some());
1287 let rest: Vec<char> = t.collect();
1288 assert_eq!(n_skipped, 0);
1289 assert_eq!(rest, vec!['a', 'c', 'a', 'b', 'a', 'b']);
1290
1291 let mut t = "ababaab".into_tokens();
1292 let n_skipped = t.skip_many(|t| parse_ab(t).is_some());
1293 let rest: Vec<char> = t.collect();
1294 assert_eq!(n_skipped, 2);
1295 assert_eq!(rest, vec!['a', 'a', 'b']);
1296 }
1297
1298 #[test]
1299 fn test_skip_many1() {
1300 let mut t = "".into_tokens();
1301 let res = t.skip_many1(parse_ab_err);
1302 let rest: String = t.collect();
1303 assert_eq!(res, Err(ABErr::NotEnoughTokens));
1304 assert_eq!(&*rest, "");
1305
1306 let mut t = "acabab".into_tokens();
1307 let res = t.skip_many1(parse_ab_err);
1308 let rest: String = t.collect();
1309 assert_eq!(res, Err(ABErr::IsNotB));
1310 assert_eq!(&*rest, "acabab");
1311
1312 let mut t = "abcbab".into_tokens();
1313 let res = t.skip_many1(parse_ab_err);
1314 let rest: String = t.collect();
1315 assert_eq!(res, Ok(1));
1316 assert_eq!(&*rest, "cbab");
1317
1318 let mut t = "ababcbab".into_tokens();
1319 let res = t.skip_many1(parse_ab_err);
1320 let rest: String = t.collect();
1321 assert_eq!(res, Ok(2));
1322 assert_eq!(&*rest, "cbab");
1323 }
1324
1325 #[test]
1326 fn test_parse_optimisations() {
1327 // Our test string.
1328 const S: &str = "345abc456";
1329
1330 fn parse_slice(mut tokens: impl Tokens<Item = char>) {
1331 // Get a start and end location to use:
1332 let from = tokens.location();
1333 tokens.take_while(|t| t.is_numeric()).consume();
1334 let to = tokens.location();
1335 tokens.set_location(from.clone());
1336
1337 // This should work (nothing will be consumed)
1338 let n = tokens
1339 .parse_slice::<u16, String>(from.clone(), to.clone())
1340 .unwrap();
1341 assert_eq!(n, 345);
1342 assert_eq!(tokens.collect::<String>(), S);
1343
1344 // reset location
1345 tokens.set_location(from.clone());
1346
1347 // This won't work (again nothing will be consumed)
1348 tokens.parse_slice::<u8, String>(from, to).unwrap_err();
1349 assert_eq!(tokens.collect::<String>(), S);
1350 }
1351
1352 fn parse_take_while(mut tokens: impl Tokens<Item = char>) {
1353 let start = tokens.location();
1354
1355 // This should work
1356 let n = tokens
1357 .parse_take_while::<u16, String, _>(|t| t.is_numeric())
1358 .unwrap();
1359 assert_eq!(n, 345);
1360 assert_eq!(tokens.collect::<String>(), "abc456");
1361
1362 // reset location
1363 tokens.set_location(start);
1364
1365 // This wont work and won't consume anything
1366 tokens
1367 .parse_take_while::<u8, String, _>(|t| t.is_numeric())
1368 .unwrap_err();
1369 assert_eq!(tokens.collect::<String>(), "345abc456");
1370 }
1371
1372 fn parse_take(mut tokens: impl Tokens<Item = char>) {
1373 let start = tokens.location();
1374
1375 // This should work
1376 let n = tokens.parse_take::<u16, String>(3).unwrap();
1377 assert_eq!(n, 345);
1378 assert_eq!(tokens.collect::<String>(), "abc456");
1379
1380 // reset location
1381 tokens.set_location(start);
1382
1383 // This wont work and won't consume anything
1384 tokens.parse_take::<u8, String>(3).unwrap_err();
1385 assert_eq!(tokens.collect::<String>(), "345abc456");
1386 }
1387
1388 // Test each method against our "optimised" StrTokens
1389 // and also the default impl of the methods via IterTokens
1390
1391 parse_slice(IterTokens::new(S.chars()));
1392 parse_slice(S.into_tokens());
1393
1394 parse_take_while(IterTokens::new(S.chars()));
1395 parse_take_while(S.into_tokens());
1396
1397 parse_take(IterTokens::new(S.chars()));
1398 parse_take(S.into_tokens());
1399 }
1400}