1#![allow(incomplete_features)]
2#![feature(generic_const_exprs, box_patterns)]
3use std::{fmt, marker::PhantomData, str::Chars};
4
5#[derive(Clone, Debug)]
6pub struct SlipperyIter<'a, I>
7where
8 I: Iterator + Sized,
9 I::Item: Clone + fmt::Debug + 'a,
10{
11 offset: usize,
12 inner: Box<[I::Item]>,
13 _marker: PhantomData<&'a [I::Item]>,
14}
15
16#[derive(Clone, Debug)]
17pub struct SlipperyCharsIter<'a> {
18 inner: SlipperyIter<'a, Chars<'a>>,
19 pub line: usize,
20 pub column: usize,
21 line_queue: Vec<usize>,
22 column_queue: Vec<usize>,
23}
24
25impl<I> From<I> for SlipperyIter<'_, I>
26where
27 I: Iterator + Clone,
28 I::Item: Clone + fmt::Debug,
29{
30 fn from(iter: I) -> Self {
31 Self {
32 offset: 0,
33 inner: iter.clone().collect::<Vec<_>>().into(),
34 _marker: PhantomData,
35 }
36 }
37}
38
39impl<'a> From<Chars<'a>> for SlipperyCharsIter<'a> {
40 fn from(iter: Chars<'a>) -> Self {
41 let mut self_ = Self {
42 inner: iter.slippery(),
43 line: 0,
44 column: 0,
45 line_queue: Vec::new(),
46 column_queue: Vec::new(),
47 };
48 self_.line_queue.reserve(16);
49 self_.column_queue.reserve(16);
50 self_
51 }
52}
53
54pub trait IntoSlipperyIterator<'a>: IntoIterator {
55 type Item;
56 type IntoSlipperyIter: Iterator<Item = <Self as IntoSlipperyIterator<'a>>::Item> + 'a;
57
58 fn into_slippery_iter(self) -> Self::IntoSlipperyIter;
59}
60
61pub trait IntoSlipperyCharsIterator<'a>: IntoIterator {
62 fn into_slippery_chars_iter(self) -> SlipperyCharsIter<'a>;
63}
64
65impl<'a, I: 'a, T> IntoSlipperyIterator<'a> for T
66where
67 T: IntoIterator<Item = I> + Clone + 'a,
68 T::Item: Clone + fmt::Debug,
69 T::IntoIter: Clone,
70{
71 type Item = T::Item;
72 type IntoSlipperyIter = SlipperyIter<'a, T::IntoIter>;
73
74 fn into_slippery_iter(self) -> Self::IntoSlipperyIter {
75 SlipperyIter::<'a>::from(self.into_iter())
76 }
77}
78
79impl<'a> IntoSlipperyCharsIterator<'a> for Chars<'a> {
80 fn into_slippery_chars_iter(self) -> SlipperyCharsIter<'a> {
81 SlipperyCharsIter::<'a>::from(self)
82 }
83}
84
85pub trait SlipperyIterator<'a>: Iterator
86where
87 Self: Sized,
88 <Self as Iterator>::Item: Clone + fmt::Debug,
89{
90 type Item;
91
92 fn slippery(self) -> SlipperyIter<'a, Self>;
93}
94
95#[allow(dead_code)]
96pub trait SlipperyCharsIterator<'a> {
97 fn slippery_chars(self) -> SlipperyCharsIter<'a>;
98}
99
100impl<'a, T> SlipperyIterator<'a> for T
101where
102 T: Iterator + Clone + Sized + 'a,
103 T::Item: Clone + fmt::Debug,
104{
105 type Item = T::Item;
106
107 fn slippery(self) -> SlipperyIter<'a, Self> {
108 self.into_slippery_iter()
109 }
110}
111
112impl<'a> SlipperyCharsIterator<'a> for &'a str {
113 fn slippery_chars(self) -> SlipperyCharsIter<'a> {
114 self.chars().into_slippery_chars_iter()
115 }
116}
117
118impl<I, T> Iterator for SlipperyIter<'_, I>
119where
120 I: Iterator<Item = T> + Clone,
121 I::Item: Clone + fmt::Debug,
122{
123 type Item = <I as Iterator>::Item;
124
125 fn next(&mut self) -> Option<<Self as Iterator>::Item> {
126 self.consume()
127 }
128}
129
130impl Iterator for SlipperyCharsIter<'_> {
131 type Item = char;
132
133 fn next(&mut self) -> Option<char> {
134 match self.consume() {
135 '\0' => None,
136 x => Some(x),
137 }
138 }
139}
140
141#[allow(dead_code)]
142impl<I, T> SlipperyIter<'_, I>
143where
144 I: Iterator<Item = T>,
145 I::Item: Clone + fmt::Debug,
146{
147 pub fn peek_forward(&self) -> Option<I::Item> {
148 self.peek_forward_many::<1>().first()?.clone()
149 }
150
151 pub fn peek_forward_many<const AMOUNT: usize>(&self) -> Box<[Option<I::Item>]> {
152 let (mut v, mut o) = (Vec::new(), self.offset);
153 for _ in 0..AMOUNT {
154 if o >= self.inner.len() || o >= usize::MAX - 1 {
155 v.push(None);
156 } else {
157 v.push(Some(self.inner[o].clone()));
158 o = o.saturating_add(1);
159 }
160 }
161 v.into_boxed_slice()
162 }
163
164 pub fn peek_backward(&self) -> Option<I::Item> {
165 self.peek_backward_many::<1>().first()?.clone()
166 }
167
168 pub fn peek_backward_many<const AMOUNT: usize>(&self) -> Box<[Option<I::Item>]> {
169 let (mut v, mut o) = (Vec::new(), self.offset.saturating_sub(1));
170 for _ in 0..AMOUNT {
171 let x = &self.inner[o];
172 o = o.saturating_sub(1);
173 v.push(Some(x.clone()));
174 }
175 v.into_boxed_slice()
176 }
177
178 fn look_around<const AMOUNT: usize, const L: isize, const DIR: bool>(
179 &self,
180 ) -> Box<[Option<I::Item>]>
181 where
182 [(); AMOUNT + L.unsigned_abs()]: Sized,
183 {
184 match L.signum() {
185 -1 => match DIR {
186 true => {
187 let mut v = self.peek_backward_many::<{ L.unsigned_abs() }>().to_vec();
188 v.extend(self.peek_forward_many::<AMOUNT>());
189 v.into_boxed_slice()
190 }
191 false => self.peek_backward_many::<{ AMOUNT + L.unsigned_abs() }>(),
192 },
193 1 => match DIR {
194 false => {
195 let mut v = self.peek_backward_many::<{ L.unsigned_abs() }>().to_vec();
196 v.extend(self.peek_forward_many::<AMOUNT>());
197 v.into_boxed_slice()
198 }
199 true => self.peek_forward_many::<{ AMOUNT + L.unsigned_abs() }>(),
200 },
201 0 | _ => match DIR {
202 true => self.peek_forward_many::<AMOUNT>(),
203 false => self.peek_backward_many::<AMOUNT>(),
204 },
205 }
206 }
207
208 pub fn consume(&mut self) -> Option<I::Item> {
209 self.consume_many::<1, 0>().first()?.clone()
210 }
211
212 pub fn consume_if<F>(&mut self, predicate: F) -> Option<I::Item>
213 where
214 F: FnOnce(Option<I::Item>) -> bool,
215 {
216 self
217 .consume_many_if::<_, 1, 0>(|mut v| predicate(v.remove(0)))
218 .first()?
219 .clone()
220 }
221
222 pub fn consume_if_then<F1, F2>(&mut self, predicate: F1, action: F2) -> Option<I::Item>
223 where
224 F1: FnOnce(Option<I::Item>) -> bool,
225 F2: FnOnce(Option<I::Item>) -> Option<I::Item>,
226 {
227 self.consume_if_then_else::<F1, F2, _>(predicate, action, || {})
228 }
229
230 pub fn consume_if_then_else<F1, F2, F3>(
231 &mut self,
232 predicate: F1,
233 action: F2,
234 action_else: F3,
235 ) -> Option<I::Item>
236 where
237 F1: FnOnce(Option<I::Item>) -> bool,
238 F2: FnOnce(Option<I::Item>) -> Option<I::Item>,
239 F3: FnOnce(),
240 {
241 self
242 .consume_many_if_then_else::<_, _, _, 1, 0>(
243 |v| {
244 predicate(match v.first() {
245 Some(&None) | None => None,
246 Some(Some(value)) => Some(value.clone()),
247 })
248 },
249 |bv| Box::new([action(bv.first().unwrap().clone())]),
250 action_else,
251 )
252 .first()?
253 .clone()
254 }
255
256 pub fn consume_many<const AMOUNT: usize, const L: isize>(&mut self) -> Box<[Option<I::Item>]>
257 where
258 [(); AMOUNT + L.unsigned_abs()]: Sized,
259 {
260 let v = self.look_around::<AMOUNT, L, true>();
261 self.offset = self.offset.saturating_add(AMOUNT);
262 v
263 }
264
265 pub fn consume_many_if<F, const AMOUNT: usize, const L: isize>(
266 &mut self,
267 predicate: F,
268 ) -> Box<[Option<I::Item>]>
269 where
270 F: FnOnce(Vec<Option<I::Item>>) -> bool,
271 [(); AMOUNT + L.unsigned_abs()]: Sized,
272 {
273 if predicate(self.look_around::<AMOUNT, L, true>().to_vec()) {
274 self.consume_many::<AMOUNT, L>()
275 } else {
276 Box::new([])
277 }
278 }
279
280 pub fn consume_many_if_then<F1, F2, const AMOUNT: usize, const L: isize>(
281 &mut self,
282 predicate: F1,
283 action: F2,
284 ) -> Box<[Option<I::Item>]>
285 where
286 F1: FnOnce(Vec<Option<I::Item>>) -> bool,
287 F2: FnOnce(Box<[Option<I::Item>]>) -> Box<[Option<I::Item>]>,
288 [(); AMOUNT + L.unsigned_abs()]: Sized,
289 {
290 self.consume_many_if_then_else::<F1, F2, _, AMOUNT, L>(predicate, action, || {})
291 }
292
293 pub fn consume_many_if_then_else<F1, F2, F3, const AMOUNT: usize, const L: isize>(
294 &mut self,
295 predicate: F1,
296 action: F2,
297 action_else: F3,
298 ) -> Box<[Option<I::Item>]>
299 where
300 F1: FnOnce(Vec<Option<I::Item>>) -> bool,
301 F2: FnOnce(Box<[Option<I::Item>]>) -> Box<[Option<I::Item>]>,
302 F3: FnOnce(),
303 [(); AMOUNT + L.unsigned_abs()]: Sized,
304 {
305 match self.consume_many_if::<_, AMOUNT, L>(predicate) {
306 x @ box [] => {
307 action_else();
308 x
309 }
310 y @ box [..] => action(y),
311 }
312 }
313
314 pub fn restore(&mut self) -> Option<I::Item> {
315 self.restore_many::<1, 0>().first()?.clone()
316 }
317
318 pub fn restore_if<F>(&mut self, predicate: F) -> Option<I::Item>
319 where
320 F: FnOnce(Option<I::Item>) -> bool,
321 {
322 self
323 .restore_many_if::<_, 1, 0>(|v| {
324 predicate(match v.first() {
325 Some(&None) | None => None,
326 Some(Some(value)) => Some(value.clone()),
327 })
328 })
329 .first()?
330 .clone()
331 }
332
333 pub fn restore_if_then<F1, F2>(&mut self, predicate: F1, action: F2) -> Option<I::Item>
334 where
335 F1: FnOnce(Option<I::Item>) -> bool,
336 F2: FnOnce(Option<I::Item>) -> Option<I::Item>,
337 {
338 self.restore_if_then_else::<F1, F2, _>(predicate, action, || {})
339 }
340
341 pub fn restore_if_then_else<F1, F2, F3>(
342 &mut self,
343 predicate: F1,
344 action: F2,
345 action_else: F3,
346 ) -> Option<I::Item>
347 where
348 F1: FnOnce(Option<I::Item>) -> bool,
349 F2: FnOnce(Option<I::Item>) -> Option<I::Item>,
350 F3: FnOnce(),
351 {
352 self
353 .restore_many_if_then_else::<_, _, _, 1, 0>(
354 |v| {
355 predicate(match v.first() {
356 Some(&None) | None => None,
357 Some(Some(value)) => Some(value.clone()),
358 })
359 },
360 |bv| Box::new([action(bv.first().unwrap().clone())]),
361 action_else,
362 )
363 .first()?
364 .clone()
365 }
366
367 pub fn restore_many<const AMOUNT: usize, const L: isize>(&mut self) -> Box<[Option<I::Item>]>
368 where
369 [(); AMOUNT + L.unsigned_abs()]: Sized,
370 {
371 let v = self.look_around::<AMOUNT, L, false>();
372 self.offset = self.offset.saturating_sub(AMOUNT);
373 v
374 }
375
376 pub fn restore_many_if<F, const AMOUNT: usize, const L: isize>(
377 &mut self,
378 predicate: F,
379 ) -> Box<[Option<I::Item>]>
380 where
381 F: FnOnce(Vec<Option<I::Item>>) -> bool,
382 [(); AMOUNT + L.unsigned_abs()]: Sized,
383 {
384 if predicate(self.look_around::<AMOUNT, L, false>().to_vec()) {
385 self.restore_many::<AMOUNT, L>()
386 } else {
387 Box::new([])
388 }
389 }
390
391 pub fn restore_many_if_then<F1, F2, const AMOUNT: usize, const L: isize>(
392 &mut self,
393 predicate: F1,
394 action: F2,
395 ) -> Box<[Option<I::Item>]>
396 where
397 F1: FnOnce(Vec<Option<I::Item>>) -> bool,
398 F2: FnOnce(Box<[Option<I::Item>]>) -> Box<[Option<I::Item>]>,
399 [(); AMOUNT + L.unsigned_abs()]: Sized,
400 {
401 self.restore_many_if_then_else::<F1, F2, _, AMOUNT, L>(predicate, action, || {})
402 }
403
404 pub fn restore_many_if_then_else<F1, F2, F3, const AMOUNT: usize, const L: isize>(
405 &mut self,
406 predicate: F1,
407 action: F2,
408 action_else: F3,
409 ) -> Box<[Option<I::Item>]>
410 where
411 F1: FnOnce(Vec<Option<I::Item>>) -> bool,
412 F2: FnOnce(Box<[Option<I::Item>]>) -> Box<[Option<I::Item>]>,
413 F3: FnOnce(),
414 [(); AMOUNT + L.unsigned_abs()]: Sized,
415 {
416 match self.restore_many_if::<_, AMOUNT, L>(predicate) {
417 x @ box [] => {
418 action_else();
419 x
420 }
421 y @ box [..] => action(y),
422 }
423 }
424}
425
426#[allow(dead_code)]
427impl SlipperyCharsIter<'_> {
428 pub fn position(&self) -> (usize, usize) {
429 (self.line, self.column)
430 }
431
432 pub fn peek_forward(&self) -> char {
433 *self.peek_forward_many::<1>().first().unwrap()
434 }
435
436 pub fn peek_forward_many<const AMOUNT: usize>(&self) -> [char; AMOUNT] {
437 self
438 .inner
439 .peek_forward_many::<AMOUNT>()
440 .iter()
441 .map(|x| x.unwrap_or('\0'))
442 .collect::<Vec<_>>()
443 .try_into()
444 .unwrap()
445 }
446
447 pub fn peek_backward(&self) -> char {
448 *self.peek_backward_many::<1>().first().unwrap()
449 }
450
451 pub fn peek_backward_many<const AMOUNT: usize>(&self) -> [char; AMOUNT] {
452 self
453 .inner
454 .peek_backward_many::<AMOUNT>()
455 .iter()
456 .map(|x| x.unwrap_or('\0'))
457 .collect::<Vec<_>>()
458 .try_into()
459 .unwrap()
460 }
461
462 pub fn consume(&mut self) -> char {
463 *self.consume_many::<1, 0>().first().unwrap()
464 }
465
466 pub fn consume_if<F>(&mut self, predicate: F) -> char
467 where
468 F: FnOnce(char) -> bool,
469 {
470 *self
471 .consume_many_if::<_, 1, 0>(|v| {
472 let x = *v.first().unwrap();
473 predicate(x)
474 })
475 .first()
476 .unwrap()
477 }
478
479 pub fn consume_many<const AMOUNT: usize, const L: isize>(
480 &mut self,
481 ) -> [char; AMOUNT + L.unsigned_abs()] {
482 self
483 .inner
484 .consume_many::<AMOUNT, L>()
485 .iter()
486 .filter_map(|x| {
487 if let Some(x) = x {
488 self.column_queue.push(self.column);
489 if *x == '\n' {
490 self.line_queue.push(self.line);
491 self.line += 1;
492 self.column = 0;
493 } else {
494 self.column += 1;
495 }
496 self.line_queue.truncate(16);
497 self.column_queue.truncate(16);
498 }
499 x.or(Some('\0'))
500 })
501 .collect::<Vec<_>>()
502 .try_into()
503 .unwrap()
504 }
505
506 pub fn consume_many_if<F, const AMOUNT: usize, const L: isize>(
507 &mut self,
508 predicate: F,
509 ) -> [char; AMOUNT + L.unsigned_abs()]
510 where
511 F: FnOnce(Vec<char>) -> bool,
512 {
513 let l = self
514 .inner
515 .look_around::<AMOUNT, L, true>()
516 .iter()
517 .map(|x| x.unwrap_or('\0'))
518 .collect::<Vec<_>>()
519 .into_boxed_slice();
520 if predicate(l.to_vec()) {
521 self.consume_many::<AMOUNT, L>()
522 } else {
523 ['\0'; AMOUNT + L.unsigned_abs()]
524 }
525 }
526
527 pub fn restore(&mut self) -> char {
528 *self.restore_many::<1, 0>().first().unwrap()
529 }
530
531 pub fn restore_if<F>(&mut self, predicate: F) -> char
532 where
533 F: FnOnce(char) -> bool,
534 {
535 *self
536 .restore_many_if::<_, 1, 0>(|v| {
537 let x = *v.first().unwrap();
538 predicate(x)
539 })
540 .first()
541 .unwrap()
542 }
543
544 pub fn restore_many<const AMOUNT: usize, const L: isize>(
545 &mut self,
546 ) -> [char; AMOUNT + L.unsigned_abs()] {
547 self
548 .inner
549 .restore_many::<AMOUNT, L>()
550 .iter()
551 .filter_map(|x| {
552 if let Some(x) = x {
553 self.column = self.column_queue.pop().unwrap_or(0);
554 if *x == '\n' {
555 self.line = self.line_queue.pop().unwrap_or(0);
556 }
557 }
558 x.or(Some('\0'))
559 })
560 .collect::<Vec<_>>()
561 .try_into()
562 .unwrap()
563 }
564
565 pub fn restore_many_if<F, const AMOUNT: usize, const L: isize>(
566 &mut self,
567 predicate: F,
568 ) -> [char; AMOUNT + L.unsigned_abs()]
569 where
570 F: FnOnce(Vec<char>) -> bool,
571 {
572 let l = self
573 .inner
574 .look_around::<AMOUNT, L, false>()
575 .iter()
576 .map(|x| x.unwrap_or('\0'))
577 .collect::<Vec<_>>()
578 .into_boxed_slice();
579 if predicate(l.to_vec()) {
580 self.restore_many::<AMOUNT, L>()
581 } else {
582 ['\0'; AMOUNT + L.unsigned_abs()]
583 }
584 }
585}
586
587#[cfg(test)]
588mod tests {
589 use super::{
590 IntoSlipperyCharsIterator, IntoSlipperyIterator, SlipperyCharsIter, SlipperyCharsIterator,
591 SlipperyIter, SlipperyIterator,
592 };
593 use std::ops::RangeInclusive;
594
595 #[test]
596 pub fn slippery_iter_construct_and_collect() {
597 let orig = 0..=10;
598 let orig_iter = orig.clone();
599
600 let s_iter_1: SlipperyIter<'_, RangeInclusive<i32>> = orig_iter.clone().into();
601 let s_iter_2 = orig_iter.clone().slippery();
602 let s_iter_3 = orig.into_slippery_iter();
603 let s_iter_4 = orig_iter.clone().into_slippery_iter();
604
605 assert_eq!(
606 s_iter_1.collect::<Vec<_>>(),
607 orig_iter.clone().collect::<Vec<_>>(),
608 );
609 assert_eq!(
610 s_iter_2.collect::<Vec<_>>(),
611 orig_iter.clone().collect::<Vec<_>>(),
612 );
613 assert_eq!(
614 s_iter_3.collect::<Vec<_>>(),
615 orig_iter.clone().collect::<Vec<_>>(),
616 );
617 assert_eq!(
618 s_iter_4.collect::<Vec<_>>(),
619 orig_iter.clone().collect::<Vec<_>>(),
620 );
621 }
622
623 #[test]
624 pub fn slippery_iter_peek_forward() {
625 let iter = (0..=10).slippery();
626
627 assert_eq!(iter.peek_forward(), Some(0));
628 assert_eq!(
629 iter.peek_forward_many::<7>().to_vec(),
630 [
631 Some(0),
632 Some(1),
633 Some(2),
634 Some(3),
635 Some(4),
636 Some(5),
637 Some(6)
638 ]
639 .to_vec(),
640 );
641 }
642
643 #[test]
644 pub fn slippery_iter_peek_backward() {
645 let mut iter = (0..=10).slippery();
646 iter.consume_many::<6, 0>();
647
648 assert_eq!(iter.peek_backward(), Some(5));
649 assert_eq!(
650 iter.peek_backward_many::<6>().to_vec(),
651 [Some(5), Some(4), Some(3), Some(2), Some(1), Some(0),].to_vec(),
652 );
653 }
654
655 #[test]
656 pub fn slippery_iter_consume() {
657 let mut iter = (0..=10).slippery();
658
659 assert_eq!(iter.consume(), Some(0));
660 assert_eq!(iter.peek_forward(), Some(1));
661 assert_eq!(
662 iter.consume_many::<5, 1>().to_vec(),
663 [Some(1), Some(2), Some(3), Some(4), Some(5), Some(6),].to_vec(),
664 );
665 assert_eq!(iter.peek_forward(), Some(6));
666 }
667
668 #[test]
669 pub fn slippery_iter_restore() {
670 let mut iter = (0..=10).slippery();
671
672 assert_eq!(
673 iter.consume_many::<11, 0>().to_vec(),
674 [
675 Some(0),
676 Some(1),
677 Some(2),
678 Some(3),
679 Some(4),
680 Some(5),
681 Some(6),
682 Some(7),
683 Some(8),
684 Some(9),
685 Some(10),
686 ]
687 .to_vec()
688 );
689 assert_eq!(iter.peek_forward(), None);
690 assert_eq!(iter.peek_backward(), Some(10));
691 assert_eq!(iter.restore(), Some(10));
692 assert_eq!(iter.peek_backward(), Some(9));
693 assert_eq!(
694 iter.restore_many::<5, -1>().to_vec(),
695 [Some(9), Some(8), Some(7), Some(6), Some(5), Some(4),].to_vec()
696 );
697 }
698
699 #[test]
700 #[allow(noop_method_call)]
701 pub fn slippery_chars_iter_construct_and_collect() {
702 let orig = "abcdefghijklmnopqrstuvwxyz";
703 let orig_iter = orig.clone().chars();
704
705 let s_iter_1: SlipperyCharsIter<'_> = orig_iter.clone().into();
706 let s_iter_2 = orig.clone().slippery_chars();
707 let s_iter_3 = orig_iter.clone().into_slippery_chars_iter();
708
709 assert_eq!(
710 s_iter_1.collect::<Vec<_>>(),
711 orig_iter.clone().collect::<Vec<_>>()
712 );
713 assert_eq!(
714 s_iter_2.collect::<Vec<_>>(),
715 orig_iter.clone().collect::<Vec<_>>()
716 );
717 assert_eq!(
718 s_iter_3.collect::<Vec<_>>(),
719 orig_iter.clone().collect::<Vec<_>>()
720 );
721 }
722
723 #[test]
724 pub fn slippery_chars_iter_peek_forward() {
725 let iter = "abcdefghijklmnopqrstuvwxyz".slippery_chars();
726
727 assert_eq!(iter.peek_forward(), 'a');
728 assert_eq!(
729 iter.peek_forward_many::<6>().to_vec(),
730 ['a', 'b', 'c', 'd', 'e', 'f',].to_vec()
731 );
732 }
733
734 #[test]
735 pub fn slippery_chars_iter_peek_backward() {
736 let mut iter = "abcdefghijklmnopqrstuvwxyz".slippery_chars();
737 iter.consume_many::<6, 0>();
738
739 assert_eq!(iter.peek_backward(), 'f');
740 assert_eq!(
741 iter.peek_backward_many::<6>().to_vec(),
742 ['f', 'e', 'd', 'c', 'b', 'a',].to_vec()
743 );
744 }
745
746 #[test]
747 pub fn slippery_chars_iter_consume() {
748 let mut iter = "abcdefghijklmnopqrstuvwxyz".slippery_chars();
749
750 assert_eq!(iter.consume(), 'a');
751 assert_eq!(iter.peek_forward(), 'b');
752 assert_eq!(
753 iter.consume_many::<5, 1>().to_vec(),
754 ['b', 'c', 'd', 'e', 'f', 'g',].to_vec()
755 );
756 assert_eq!(iter.peek_forward(), 'g');
757 }
758
759 #[test]
760 pub fn slippery_chars_iter_restore() {
761 let mut iter = "abcdefghijklmnopqrstuvwxyz".slippery_chars();
762
763 assert_eq!(
764 iter.consume_many::<26, 0>().to_vec(),
765 [
766 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r',
767 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
768 ]
769 .to_vec()
770 );
771 assert_eq!(iter.peek_forward(), '\0');
772 assert_eq!(iter.peek_backward(), 'z');
773 assert_eq!(iter.restore(), 'z');
774 assert_eq!(iter.peek_backward(), 'y');
775 assert_eq!(
776 iter.restore_many::<5, -1>(),
777 ['y', 'x', 'w', 'v', 'u', 't',]
778 );
779 }
780}